<?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 - Articles by Ricardo Ungureanu</title>
        <link>https://www.elastic.co/pt/security-labs</link>
        <description>Trusted security news &amp; research from the team at Elastic.</description>
        <lastBuildDate>Thu, 05 Mar 2026 22:21:01 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Elastic Security Labs - Articles by Ricardo Ungureanu</title>
            <url>https://www.elastic.co/pt/security-labs/assets/security-labs-thumbnail.png</url>
            <link>https://www.elastic.co/pt/security-labs</link>
        </image>
        <copyright>© 2026. Elasticsearch B.V. All Rights Reserved</copyright>
        <item>
            <title><![CDATA[Elastic catches DPRK passing out KANDYKORN]]></title>
            <link>https://www.elastic.co/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image3.png" alt="FinderTools execution" /></p>
<p><img src="https://www.elastic.co/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image36.png" alt="SUGARLOADER creates HLOADER" /></p>
<p><img src="https://www.elastic.co/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/image22.png" alt="send routine" /></p>
<p><img src="https://www.elastic.co/pt/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/pt/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/pt/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/pt/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/pt/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/pt/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/pt/security-labs/assets/images/elastic-catches-dprk-passing-out-kandykorn/photo-edited-01@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[The DPRK strikes using a new variant of RUSTBUCKET]]></title>
            <link>https://www.elastic.co/pt/security-labs/DPRK-strikes-using-a-new-variant-of-rustbucket</link>
            <guid>DPRK-strikes-using-a-new-variant-of-rustbucket</guid>
            <pubDate>Fri, 14 Jul 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Watch out! We’ve recently discovered a variant of RUSTBUCKET. Read this article to understand the new capabilities we’ve observed, as well as how to identify it in your own network.]]></description>
            <content:encoded><![CDATA[<h2>Key takeaways</h2>
<ul>
<li>The RUSTBUCKET malware family is in an active development phase, adding built-in persistence and focusing on signature reduction.</li>
<li>REF9135 actors are continually shifting their infrastructure to evade detection and response.</li>
<li>The DPRK continues financially motivated attacks against cryptocurrency service providers.</li>
<li>If you are running Elastic Defend, you are protected from REF9135</li>
</ul>
<h2>Preamble</h2>
<p>The Elastic Security Labs team has detected a new variant of the RUSTBUCKET malware, a family that has been previously attributed to the BlueNorOff group by <a href="https://www.jamf.com/blog/bluenoroff-apt-targets-macos-rustbucket-malware/">Jamf Threat Labs</a> in April 2023.</p>
<p>This variant of RUSTBUCKET, a malware family that targets macOS systems, adds persistence capabilities not previously observed and, at the time of reporting, is undetected by VirusTotal signature engines. Elastic Defend behavioral and prebuilt detection rules provide protection and visibility for users. We have also released a signature to prevent this malware execution.</p>
<p>The research into REF9135 used host, binary, and network analysis to identify and attribute intrusions observed by this research team, and other intelligence groups, with high confidence to the Lazarus Group; a cybercrime and espionage organization operated by the Democratic People’s Republic of North Korea (DPRK).</p>
<p>This research will describe:</p>
<ul>
<li>REF9135’s use of RUSTBUCKET for sustained operations at a cryptocurrency payment services provider</li>
<li>Reversing of an undetected variant of RUSTBUCKET that adds a built-in persistence mechanism</li>
<li>How victimology, initial infection, malware, and network C2 intersections from first and third-party collection align with previous Lazarus Group reporting</li>
</ul>
<h2>RUSTBUCKET code analysis</h2>
<h3>Overview</h3>
<p>Our research has identified a persistence capability not previously seen in the RUSTBUCKET family of malware, leading us to believe that this family is under active development. Additionally, at the time of publication, this new variant has zero detections on VirusTotal and is leveraging a dynamic network infrastructure methodology for command and control.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image1.jpg" alt="Execution flow of REF9135" /></p>
<h3>Stage 1</h3>
<p>During Stage 1, the process begins with the execution of an AppleScript utilizing the <strong>%2Fusr%2Fbin%2Fosascript</strong> command. This AppleScript is responsible for initiating the download of the Stage 2 binary from the C2 using cURL. This session includes the string <strong>pd</strong> in the body of the HTTP request and <strong>cur1-agent</strong> as the User-Agent string which saves the Stage 2 binary to <strong>%2Fusers%2Fshared%2F.pd,</strong> (<a href="https://www.virustotal.com/gui/file/7887638bcafd57e2896c7c16698e927ce92fd7d409aae698d33cdca3ce8d25b8">7887638bcafd57e2896c7c16698e927ce92fd7d409aae698d33cdca3ce8d25b8</a>).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image2.jpg" alt="Stage 1 command line" /></p>
<h3>Stage 2</h3>
<p>The Stage 2 binary ( <strong>.pd</strong> ) is compiled in Swift and operates based on command-line arguments. The binary expects a C2 URL to be provided as the first parameter when executed. Upon execution, it invokes the <strong>downAndExec</strong> function, which is responsible for preparing a POST HTTP request. To initiate this request, the binary sets the User-Agent string as <strong>mozilla%2F4.0 (compatible; msie 8.0; windows nt 5.1; trident%2F4.0)</strong> and includes the string <strong>pw</strong> in the body of the HTTP request.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image12.jpg" alt="Setting the HTTP parameters before sending the request" /></p>
<p>During execution, the malware utilizes specific macOS APIs for various operations. It begins with <a href="https://developer.apple.com/documentation/foundation/nsfilemanager">NSFileManager's</a> <strong>temporaryDirectory</strong> function to obtain the current temporary folder, then generates a random UUID using <a href="https://developer.apple.com/documentation/foundation/nsuuid">NSUUID's</a> <strong>UUID.init</strong> method. Finally, the malware combines the temporary directory path with the generated UUID to create a unique file location and writes the payload to it.</p>
<p>Once the payload, representing Stage 3 of the attack is written to disk, the malware utilizes <a href="https://developer.apple.com/documentation/foundation/nstask">NSTask</a> to initiate its execution.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image11.jpg" alt="Generating the Stage 3 file path" /></p>
<h3>Stage 3</h3>
<p>In Stage 3, the malware (<a href="https://www.virustotal.com/gui/file/9ca914b1cfa8c0ba021b9e00bda71f36cad132f27cf16bda6d937badee66c747">9ca914b1cfa8c0ba021b9e00bda71f36cad132f27cf16bda6d937badee66c747</a>) is a FAT macOS binary that supports both ARM and Intel architectures written in Rust. It requires a C2 URL to be supplied as a parameter.</p>
<p>The malware initiates its operations by dynamically generating a 16-byte random value at runtime. This value serves as a distinctive identifier for the specific instance of the active malware. Subsequently, the malware proceeds to gather comprehensive system information, including:</p>
<ul>
<li>Computer name</li>
<li>List of active processes</li>
<li>Current timestamp</li>
<li>Installation timestamp</li>
<li>System boot time</li>
<li>Status of all running processes within the system</li>
</ul>
<p>The malware establishes its initial connection to the C2 server by transmitting the gathered data via a POST request. The request is accompanied by a User-Agent string formatted as <strong>Mozilla%2F4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident%2F4.0)</strong>.</p>
<p>Upon receiving the request, the C2 server responds with a command ID, which serves as an instruction for the malware. The malware is designed to handle only two commands.</p>
<h4>Command ID 0x31</h4>
<p>This command directs the malware to self-terminate.</p>
<h4>Command ID 0x30</h4>
<p>This command enables the operator to upload malicious Mach-O binaries or shell scripts to the system and execute them. The payload is stored in a randomly generated temporary path and created within the current user TMP directory following the naming convention of <strong><code>$TMPDIR%2F.\&lt;8 random digits\&gt;</code></strong></p>
<p>Below is a summary of the command structure, indicating the constants, arguments, and payload components for easy comprehension.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image5.jpg" alt="Command structure example" /></p>
<p>The malware proceeds by granting execution permissions to the uploaded file using the <strong>chmod</strong> API.</p>
<p>After executing the payload, the malware sends a status update to the server, notifying it of the completed execution, and then sleeps for 60 seconds. Following this delay, the malware loops to collect system information once again and remains in a waiting state, anticipating the arrival of the next command from the server</p>
<h3>The undetected version of RUSTBUCKET</h3>
<p>Using code similarities from the sample in our telemetry, we searched VirusTotal and identified an undetected variant of RUSTBUCKET.</p>
<p>As of the publication of this research, the <a href="https://www.virustotal.com/gui/file/de81e5246978775a45f3dbda43e2716aaa1b1c4399fe7d44f918fccecc4dd500">newly discovered version</a> of the malware has not been flagged by any antivirus engines on VirusTotal. A thorough analysis of the sample brought to light the addition of a new persistence capability and C2 infrastructure. The behavioral rules for Elastic Defend prevent, and Elastic’s prebuilt detection rules identify, this activity. We have also released a signature that will prevent this new variant of RUSTBUCKET.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image7.png" alt="VirusTotal results at the time of publication" /></p>
<h3>Persistence</h3>
<p>A predominant method utilized by malware to achieve persistence on macOS is through the utilization of LaunchAgents. In macOS, users have individual LaunchAgents folders within their Library directory, enabling them to define code that executes upon each user login. Additionally, a system-level LaunchAgents folder exists, capable of executing code for all users during the login process. Elastic Defend monitors for the creation of LaunchAgents and LaunchDaemons containing malicious or suspicious values as a way to detect these persistence techniques.</p>
<p>In the case of this updated RUSTBUCKET sample, it establishes its own persistence by adding a plist file at the path <strong><code>%2FUsers%2F\&lt;user\&gt;%2FLibrary%2FLaunchAgents%2Fcom.apple.systemupdate.plist</code></strong> , and it copies the malware’s binary to the following path <strong><code>%2FUsers%2F\&lt;user\&gt;%2FLibrary%2FMetadata%2FSystem Update</code></strong>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image9.jpg" alt="File content of plist used for persistence" /></p>
<p>There are several elements of the plist file, using standard true%2Ffalse or string values:</p>
<ul>
<li><strong>Label:</strong> The key &quot;Label&quot; specifies the name of the LaunchAgent, which in this case is <strong>com.apple.systemupdate</strong>. This expects a string value.</li>
<li><strong>RunAtLoad:</strong> This indicates that the LaunchAgent should execute its associated code immediately upon loading, specifically during system startup or user login. This expects a true%2Ffalse value.</li>
<li><strong>LaunchOnlyOnce:</strong> This prevents the malware from being executed multiple times concurrently and expects a true%2Ffalse value.</li>
<li><strong>KeepAlive:</strong> This key instructs the system to keep the LaunchAgent running and relaunch it if it terminates unexpectedly. This expects a true%2Ffalse value.</li>
<li><strong>ProgramArguments:</strong> The &quot;ProgramArguments&quot; key specifies an array of strings that define the program or script to be executed by the LaunchAgent. This expects a string value and in this case, the LaunchAgent executes the file located at <strong>&quot;<code>%2FUsers%2F\&lt;user\&gt;%2FLibrary%2FMetadata%2FSystem Update</code>&quot;</strong> and provides the C2 URL <strong>&quot;https:%2F%2Fwebhostwatto.work[.]gd&quot;</strong> as an argument to the malware.</li>
</ul>
<h2>RUSTBUCKET and REF9135 analysis</h2>
<h3>Overview</h3>
<p>The RUSTBUCKET campaign has previously been associated with BlueNorOff by Jamf and Sekoia.io. BlueNorOff is believed to be operating at the behest of the DPRK for the purposes of financial gain in order to ease the strain of global sanctions. BlueNorOff is a sub-unit of the overarching DPRK offensive cyber attack organization, the <a href="https://attack.mitre.org/groups/G0032/">Lazarus Group</a>. The <a href="https://www.nytimes.com/interactive/2018/05/03/magazine/money-issue-bangladesh-billion-dollar-bank-heist.html">2016 Bangladesh Bank robbery</a> stands out as BlueNorOff's most notorious attack, wherein their objective was to illicitly transfer over $850M from the Federal Reserve Bank of New York account owned by Bangladesh Bank, the central bank of Bangladesh, by exploiting the SWIFT network.</p>
<blockquote>
<p>As an analyst note, if you’re interested in a tremendously verbose and detailed walkthrough of this intrusion, Geoff White and Jean Lee released a 19-part podcast through the <a href="https://www.bbc.co.uk/programmes/w13xtvg9/episodes/downloads">BBC World Service</a> that is an unbelievable account of this event.</p>
</blockquote>
<h3>Networking infrastructure</h3>
<p>The persistence mechanism identified previously calls out to <strong>https:%2F%2Fwebhostwatto.work[.]gd</strong>. Third-party research into this URL indicates that 12%2F89 <a href="https://www.virustotal.com/gui/url/e299c9f2233f025256ab29d53d070a8f94d1c2c1a2b6f3a7c13e16df185e9e32/detection">VirusTotal</a> vendors have identified it as malicious, and it exists within a community collection documenting the <a href="https://www.cyfirma.com/outofband/tracking_dangerouspassword_campaign_by_lazarusgroup/">DangerousPassword phishing campaign</a>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image6.png" alt="VT detections and community collections for https://webhostwatto.work[.]gd" /></p>
<p>VirusTotal <a href="https://www.virustotal.com/gui/domain/webhostwatto.work.gd/detection">last saw</a> the domain pointing to <strong>104.168.167[.]88</strong>. Which has been specifically identified in a Sekoia.io <a href="https://blog.sekoia.io/bluenoroffs-rustbucket-campaign/">blog</a> in May as part of BlueNorOff’s RUSTBUCKET campaign.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image4.jpg" alt="Updated RUSTBUCKET IP (104.168.167[.]88) previously identified by Sekoia.io" /></p>
<p>Further connecting <strong>webhostwatto.work[.]gd</strong> to DangerousPassword, BlueNorOff, and the DPRK campaigns, this domain shares a TLS leaf certificate fingerprint hash ( <strong>1031871a8bb920033af87078e4a418ebd30a5d06152cd3c2c257aecdf8203ce6</strong> ) with another domain, <strong>companydeck[.]online</strong>.</p>
<p><strong>companydesk[.]online</strong> is included in the <a href="https://www.virustotal.com/graph/g6e8b200cfd774d129558fa5715c83d1bc81099f5cd7643719580be988ec01b8f">VirusTotal Graph</a> (VirusTotal account required) for <a href="https://attack.mitre.org/groups/G0082/">APT38</a>, which is also known as DangerousPassword, BlueNorOff, etc.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image3.jpg" alt="Selection from the VirusTotal Graph for DangerousPassword" /></p>
<p>DangerousPassword and BlueNorOff are campaigns that have both been previously associated with the DPRK.</p>
<p>Using the IP address (<strong>64.44.141[.]15</strong>) for our initial C2 domain, <strong>crypto.hondchain[.]com</strong>, we uncovered 3 additional C2 domains:</p>
<ul>
<li><strong>starbucls[.]xyz</strong></li>
<li><strong>jaicvc[.]com</strong></li>
<li><strong>docsend.linkpc[.]net</strong> (dynamic DNS domain)</li>
</ul>
<p>While there are only 5 hosts (4 total domains) registered to the C2 IP address (indicating that this was not a high-capacity hosting server), we looked for additional relationships to increase the association confidence between the domains. To do this, we replicated the same fingerprinting process previously used with <strong>webhostwatto.work[.]gd</strong>. The TLS fingerprint hash for <strong>starbucls[.]xyz</strong> ( <strong>788261d948177acfcfeb1f839053c8ee9f325bd6fb3f07637a7465acdbbef76a</strong> ) is the same fingerprint as <strong>jaicvc[.]com</strong>.</p>
<p>With these two domains having the same TLS fingerprint hash and the fact that they were both registered to the IP address, we were able to cluster these atomic entities, and their siblings, together with high confidence:</p>
<ul>
<li>All hosts were registered to <strong>64.44.141[.]15</strong></li>
<li><strong>starbucls[.]xyz</strong> and <strong>crypto.hondchain[.]com</strong> were observed being used by our malware samples</li>
<li><strong>starbucls[.]xyz</strong> and <strong>jaicvc[.]com</strong> shared a TLS fingerprint</li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image8.jpg" alt="Domains registered to REF9135 C2 IP address" /></p>
<p>Looking at the “First” column (when they were first observed through 3rd party passive DNS), these hosts are being created rapidly, likely as an attempt to stay ahead of detection efforts by research teams. We are associating the following domains and IP address to the REF9135 campaign with high confidence:</p>
<ul>
<li><strong>starbucls[.]xyz</strong></li>
<li><strong>jaicvc[.]com</strong></li>
<li><strong>crypto.hondchain[.]com</strong></li>
<li><strong>64.44.141[.]15</strong></li>
</ul>
<p>We have not observed <strong>docsend.linkpc[.]net</strong> being used with the RUSTBUCKET samples we analyzed. However, its shared IP registration and host siblings lead us to state with a moderate degree of confidence that it is directly related to RUSTBUCKET and REF9135 as C2 infrastructure; and a high degree of confidence that it is malicious (shared infrastructure as part of other campaigns).</p>
<h3>Defense evasion</h3>
<p>The campaign owners used techniques to hinder the collection of Stage 2 and Stage 3 binaries by analysts who may have overlooked User-Agent strings in their investigations, as well as internet scanners and sandboxes focused on collecting malicious binaries.</p>
<p>As outlined in the Stage 1 section, there is a specific User-Agent string ( <strong>cur1-agent</strong> ) that is expected when downloading the Stage 2 binary, if you do not use the expected User-Agent, you will be provided with a 405 HTTP response status code (Method Not Allowed).</p>
<p>It also appears that the campaign owners are monitoring their payload staging infrastructure. Using the expected User-Agent for the Stage 3 binary download (<strong>mozilla%2F4.0 (compatible; msie 8.0; windows nt 5.1; trident%2F4.0)</strong>), we were able to collect the Stage 3 binary.</p>
<p>Finally, we observed REF9135 changing its C2 domain once we began to collect the Stage 2 and 3 binaries for analysis. When making subsequent requests to the original server (<strong>crypto.hondchain[.]com</strong>), we received a 404 HTTP response status code (Not Found) and shortly after, a new C2 server was identified (<strong>starbucls[.]xyz</strong>). This could be because we caught the binary before it was rolled off as part of a normal operational security practice (don’t leave your valuable payload attached to the Internet to be discovered) or because they observed a connection to their infrastructure that was not from their targeted network.</p>
<p>Of note, while the User-Agent strings above could initially appear to be the default cURL or Firefox User-Agents strings to an analyst, they are not. The default cURL User-Agent string is <strong>curl%2Fversion.number</strong> whereas the malware uses <strong>cur1-agent</strong> (using a <strong>1</strong> in place of the <strong>l</strong> in “curl”). Additionally, the “Firefox” string is all lowercase (<strong>mozilla%2F4.0 (compatible; msie 8.0; windows nt 5.1; trident%2F4.0)</strong>), unlike actual <a href="https://www.useragentstring.com/pages/Firefox/">Firefox User-Agent strings</a> which are camel-cased.</p>
<p>This requirement to download payloads allows the attackers to restrict distribution to only requestors who know the correct UA string. This provides strong protection against both scanning services and researchers, who would otherwise have early access to hosted malicious files for analysis and detection engineering.</p>
<h3>Victimology</h3>
<p>The REF9135 victim is a venture-backed cryptocurrency company providing services to businesses such as payroll and business-to-business transactions with a headquarters in the United States. This victim fits the mold from prior reporting on BlueNorOff targeting organizations with access to large amounts of cryptocurrency for theft.</p>
<h2>Observed adversary tactics and techniques</h2>
<p>Elastic uses the MITRE ATT&amp;CK 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/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/TA0008/">Lateral movement</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011">Command and control</a></li>
</ul>
<h2>Diamond model</h2>
<p>Elastic Security 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) 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/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image13.jpg" alt="REF9135 Diamond Model" /></p>
<h2>Detection logic</h2>
<h3>Prevention</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_RustBucket.yar">MacOS.Trojan.RustBucket</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/persistence_persistence_via_suspicious_launch_agent_or_launch_daemon.toml">Persistence via Suspicious Launch Agent or Launch Daemon</a></li>
</ul>
<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 behaviors observed in REF9135.</p>
<p><strong>Suspicious Curl File Download via Osascript</strong></p>
<pre><code>process where process.parent.name : &quot;osascript&quot; and process.name : &quot;curl&quot; and process.args : &quot;-o&quot;
</code></pre>
<p><strong>Suspicious URL as argument to Self-Signed Binary</strong></p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and 
 process.code_signature.trusted == false and 
 process.code_signature.signing_id regex~ &quot;&quot;&quot;[A-Za-z0-9\_\s]{2,}\-[a-z0-9]{40}&quot;&quot;&quot; and 
 process.args : &quot;http*&quot; and process.args_count &lt;= 3
</code></pre>
<h4>YARA</h4>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the RUSTBUCKET malware:</p>
<pre><code> rule MacOS_Trojan_RustBucket {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-06-26&quot;
        last_modified = &quot;2023-06-26&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;MacOS&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;RustBucket&quot;
        threat_name = &quot;MacOS.Trojan.RustBucket&quot;
        reference_sample = &quot;9ca914b1cfa8c0ba021b9e00bda71f36cad132f27cf16bda6d937badee66c747&quot;
        severity = 100

    strings:
        $user_agent = &quot;User-AgentMozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)&quot;
        $install_log = &quot;/var/log/install.log&quot;
        $timestamp = &quot;%Y-%m-%d %H:%M:%S&quot;
    condition:
        all of them
}
</code></pre>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.jamf.com/blog/bluenoroff-apt-targets-macos-rustbucket-malware/">https:%2F%2Fwww.jamf.com%2Fblog%2FBlueNorOff-apt-targets-macos-rustbucket-malware%2F</a></li>
<li><a href="https://blog.sekoia.io/bluenoroffs-rustbucket-campaign/">https:%2F%2Fblog.sekoia.io%2FBlueNorOffs-rustbucket-campaign%2F</a></li>
</ul>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/rustbucket">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>webhostwatto.work[.]gd</td>
<td>Domain</td>
<td>N%2FA</td>
<td>REF9135 C2 domain</td>
</tr>
<tr>
<td>crypto.hondchain[.]com</td>
<td>Domain</td>
<td>N%2FA</td>
<td>REF9135 C2 domain</td>
</tr>
<tr>
<td>starbucls[.]xyz</td>
<td>Domain</td>
<td>N%2FA</td>
<td>REF9135 C2 domain</td>
</tr>
<tr>
<td>jaicvc[.]com</td>
<td>Domain</td>
<td>N%2FA</td>
<td>REF9135 C2 domain</td>
</tr>
<tr>
<td>docsend.linkpc[.]net</td>
<td>Domain</td>
<td>N%2FA</td>
<td>REF9135 C2 domain</td>
</tr>
<tr>
<td>companydeck[.]online</td>
<td>Domain</td>
<td>N%2FA</td>
<td>Associated by REF9135 TLS fingerprint hash</td>
</tr>
<tr>
<td>104.168.167[.]88</td>
<td>ipv4</td>
<td>N%2FA</td>
<td>REF9135 C2 IP address</td>
</tr>
<tr>
<td>64.44.141[.]15</td>
<td>ipv4</td>
<td>N%2FA</td>
<td>REF9135 C2 IP address</td>
</tr>
<tr>
<td>788261d948177acfcfeb1f839053c8ee9f325bd6fb3f07637a7465acdbbef76a</td>
<td>x509-certificate</td>
<td>jaicvc[.]com</td>
<td>REF9135 C2 TLS fingerprint hash</td>
</tr>
<tr>
<td>1031871a8bb920033af87078e4a418ebd30a5d06152cd3c2c257aecdf8203ce6</td>
<td>x509-certificate</td>
<td>webhostwatto.work[.]gd</td>
<td>REF9135 C2 TLS fingerprint hash</td>
</tr>
<tr>
<td>9ca914b1cfa8c0ba021b9e00bda71f36cad132f27cf16bda6d937badee66c747</td>
<td>SHA-256</td>
<td>N%2FA</td>
<td>MacOS.Trojan.RustBucket</td>
</tr>
<tr>
<td>7fccc871c889a4f4c13a977fdd5f062d6de23c3ffd27e72661c986fae6370387</td>
<td>SHA-256</td>
<td>N%2FA</td>
<td>MacOS.Trojan.RustBucket</td>
</tr>
<tr>
<td>ec8f97d5595d92ec678ffbf5ae1f60ce90e620088927f751c76935c46aa7dc41</td>
<td>SHA-256</td>
<td>N%2FA</td>
<td>MacOS.Trojan.RustBucket</td>
</tr>
<tr>
<td>de81e5246978775a45f3dbda43e2716aaa1b1c4399fe7d44f918fccecc4dd500</td>
<td>SHA-256</td>
<td>ErrorCheck</td>
<td>MacOS.Trojan.RustBucket</td>
</tr>
<tr>
<td>4f49514ab1794177a61c50c63b93b903c46f9b914c32ebe9c96aa3cbc1f99b16</td>
<td>SHA-256</td>
<td>N%2FA</td>
<td>MacOS.Trojan.RustBucket</td>
</tr>
<tr>
<td>fe8c0e881593cc3dfa7a66e314b12b322053c67cbc9b606d5a2c0a12f097ef69</td>
<td>SHA-256</td>
<td>N%2FA</td>
<td>MacOS.Trojan.RustBucket</td>
</tr>
<tr>
<td>7887638bcafd57e2896c7c16698e927ce92fd7d409aae698d33cdca3ce8d25b8</td>
<td>SHA-256</td>
<td>%2FUsers%2FShared%2F.pd</td>
<td>Stage 2</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/photo-edited-12@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Initial research exposing JOKERSPY]]></title>
            <link>https://www.elastic.co/pt/security-labs/inital-research-of-jokerspy</link>
            <guid>inital-research-of-jokerspy</guid>
            <pubDate>Wed, 21 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Explore JOKERSPY, a recently discovered campaign that targets financial institutions with Python backdoors. This article covers reconnaissance, attack patterns, and methods of identifying JOKERSPY in your network.]]></description>
            <content:encoded><![CDATA[<h2>Key takeaways</h2>
<ul>
<li>This is an initial notification of an active intrusion with additional details to follow</li>
<li>REF9134 leverages custom and open source tools for reconnaissance and command and control</li>
<li>Targets of this activity include a cryptocurrency exchange in Japan</li>
</ul>
<h2>Preamble</h2>
<p>This research article explores a recently discovered intrusion we’re calling REF9134, which involves using the <strong>sh.py</strong> backdoor to deploy the macOS Swiftbelt enumeration tool. <strong>sh.py</strong> and <strong>xcc</strong> have recently been dubbed <a href="https://www.bitdefender.com/blog/labs/fragments-of-cross-platform-backdoor-hint-at-larger-mac-os-attack/">JOKERSPY</a> by Bitdefender.</p>
<p>Specifically, this research covers:</p>
<ul>
<li>How Elastic Security Labs identified reconnaissance from the adversary group</li>
<li>The adversary’s steps to evade detection using <strong>xcc</strong> , installing the <strong>sh.py</strong> backdoor, and deploying enumeration tools</li>
</ul>
<p>A deeper look at this attack may be published at a later date.</p>
<h2>Overview</h2>
<p>In late May of 2023, an adversary with existing access in a prominent Japanese cryptocurrency exchange tripped one of our diagnostic endpoint alerts that detected the execution of a binary ( <strong>xcc</strong> ). <strong>xcc</strong> is not trusted by Apple, and the adversary self-signed using the native macOS tool <strong>codesign</strong>. While this detection in itself was not necessarily innocuous, the industry vertical and additional activity we observed following these initial alerts caught our eye and caused us to pay closer attention.</p>
<p>Following the execution of <strong>xcc</strong> , we observed the threat actor attempting to bypass TCC permissions by creating their own TCC database and trying to replace the existing one. On June 1st a new Python-based tool was seen executing from the same directory as <strong>xcc</strong> and was utilized to execute an open-source macOS post-exploitation enumeration tool known as Swiftbelt.</p>
<h2>Analysis</h2>
<p>REF9134 is an intrusion into a large Japan-based cryptocurrency service provider focusing on asset exchange for trading Bitcoin, Ethereum, and other common cryptocurrencies.</p>
<h3>The xcc binary</h3>
<p><strong>xcc</strong> ( <strong>d895075057e491b34b0f8c0392b44e43ade425d19eaaacea6ef8c5c9bd3487d8</strong> ) is a self-signed multi-architecture binary written in Swift which is used to evaluate current system permissions. The version observed by Elastic Security Labs is signed as <strong>XProtectCheck-55554944f74096a836b73310bd55d97d1dff5cd4</strong> , and has a code signature resembling <a href="https://objective-see.org/blog/blog_0x73.html">publicly known</a> and untrusted payloads.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/inital-research-of-jokerspy/image8.png" alt="Initial detection of the xcc binary" /></p>
<p>To identify other binaries signed with the same identifier, we converted <strong>XProtectCheck-55554944f74096a836b73310bd55d97d1dff5cd4</strong> to hexadecimal and searched VirusTotal to identify 3 additional samples ( <strong>content:{5850726f74656374436865636b2d35353535343934346637343039366138333662373333313062643535643937643164666635636434}</strong> ).</p>
<p>Each contained the same core functionality with structural differences. These discrepancies may indicate that these variants of <strong>xcc</strong> were developed to bypass endpoint capabilities that interfered with execution.</p>
<p>Shortly after the creation of <strong>xcc</strong> , researchers observed the threat actor copying <strong>/Users/Shared/tcc.db</strong> over the existing TCC database, <strong>/Library/Application Support/com.apple.TCC/TCC.db</strong>. This may enable the threat to avoid TCC prompts visible to system users while simultaneously abusing a directory with broad file write permissions.</p>
<h4>XCode artifacts</h4>
<p>During analysis of this binary, researchers identified two unique paths, <strong>/Users/joker/Developer/Xcode/DerivedData/</strong> and <strong>/Users/joker/Downloads/Spy/XProtectCheck/XProtectCheck/</strong> , which stood out as anomalous. The default path for compiling code with Xcode is <strong>/Users/[username]/Developer/Xcode/DerivedData</strong>.</p>
<h4>Abusing TCC</h4>
<p>These introspection permissions are managed by the native Transparency, Consent, and Control (TCC) feature. Researchers determined that <strong>xcc</strong> checks FullDiskAccess and ScreenRecording permissions, as well as checking if the screen is currently locked and if the current process is a trusted accessibility client.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/inital-research-of-jokerspy/image2.jpg" alt="xcc queries current system permissions" /></p>
<p>Upon successfully executing in our <a href="https://www.elastic.co/pt/security-labs/click-click-boom-automating-protections-testing-with-detonate">Detonate</a> environment, the following results were displayed:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/inital-research-of-jokerspy/image3.jpg" alt="TCC permissions queried by xcc" /></p>
<p>Once the custom TCC database was placed in the expected location, the threat actor executed the <strong>xcc</strong> binary.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/inital-research-of-jokerspy/image4.jpg" alt="Threat actor creating/modifying, moving a TCC database, and then executing xcc" /></p>
<h4>Initial access</h4>
<p>The <strong>xcc</strong> binary was executed via bash by three separate processes</p>
<ul>
<li><strong>/Applications/IntelliJ IDEA.app/Contents/MacOS/idea</strong></li>
<li><strong>/Applications/iTerm.app/Contents/MacOS/iTerm2</strong></li>
<li><strong>/Applications/Visual Studio Code.app/Contents/MacOS/Electron.</strong></li>
</ul>
<p>While we are still investigating and continuing to gather information, we strongly believe that the initial access for this malware was a malicious or backdoored plugin or 3rd party dependency that provided the threat actor access. This aligns with the connection that was made by the researchers at <a href="https://www.bitdefender.com/blog/labs/fragments-of-cross-platform-backdoor-hint-at-larger-mac-os-attack/">Bitdefender</a> who correlated the hardcoded domain found in a version of the <strong>sh.py</strong> backdoor to a Tweet about an infected macOS QR code reader which was found to have a malicious dependency.</p>
<h4>Deployed cryptographic libraries</h4>
<p>On May 31st, researchers observed three non-native <a href="https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/UsingDynamicLibraries.html">DyLibs</a> deployed to <strong>/Users/shared/keybag/</strong> called <strong>libcrypto.1.0.0.dylib</strong> , <strong>libncursesw.5.dylib</strong> , and <strong>libssl.1.0.0.dylib</strong>. On MacOS, keys for file and keychain Data Protection are stored in <a href="https://support.apple.com/en-au/guide/security/sec6483d5760/web">keybags</a>, and pertain to iOS, iPadOS, watchOS, and tvOS. At this time, researchers propose that this staging serves a defense evasion purpose and speculate that they may contain useful vulnerabilities. The threat actor may plan to introduce these vulnerabilities to otherwise patched systems or applications.</p>
<h4>The sh.py backdoor</h4>
<p><strong>sh.py</strong> is a Python backdoor used to deploy and execute other post-exploitation capabilities like Swiftbelt <strong>.</strong></p>
<p>The malware loads its configuration from <strong>~/Public/Safari/sar.dat</strong>. The configuration file contains crucial elements such as command-and-control (C2) URLs, a sleep timer for beaconing purposes (the default value is 5 seconds), and a unique nine-digit identifier assigned to each agent.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/inital-research-of-jokerspy/image5.jpg" alt="Execution of sh.py with the C2 URL provided as a parameter" /></p>
<p>As part of its periodic beaconing, the malware gathers and transmits various system information. The information sent includes:</p>
<ul>
<li>Hostname</li>
<li>Username</li>
<li>Domain name</li>
<li>Current directory</li>
<li>The absolute path of the executable binary</li>
<li>OS version</li>
<li>Is 64-bit OS</li>
<li>Is 64-bit process</li>
<li>Python version</li>
</ul>
<p>Below is a table outlining the various commands that can be handled by the backdoor:</p>
<table>
<thead>
<tr>
<th>Command</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>sk</td>
<td>Stop the backdoor's execution</td>
</tr>
<tr>
<td>l</td>
<td>List the files of the path provided as parameter</td>
</tr>
<tr>
<td>c</td>
<td>Execute and return the output of a shell command</td>
</tr>
<tr>
<td>cd</td>
<td>Change directory and return the new path</td>
</tr>
<tr>
<td>xs</td>
<td>Execute a Python code given as a parameter in the current context</td>
</tr>
<tr>
<td>xsi</td>
<td>Decode a Base64-encoded Python code given as a parameter, compile it, then execute it</td>
</tr>
<tr>
<td>r</td>
<td>Remove a file or directory from the system</td>
</tr>
<tr>
<td>e</td>
<td>Execute a file from the system with or without parameter</td>
</tr>
<tr>
<td>u</td>
<td>Upload a file to the infected system</td>
</tr>
<tr>
<td>d</td>
<td>Download a file from the infected system</td>
</tr>
<tr>
<td>g</td>
<td>Get the current malware's configuration stored in the configuration file</td>
</tr>
<tr>
<td>w</td>
<td>Override the malware's configuration file with new values</td>
</tr>
</tbody>
</table>
<h3>Swiftbelt</h3>
<p>On June 1st, the compromised system registered a signature alert for <a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Hacktool_Swiftbelt.yar">MacOS.Hacktool.Swiftbelt</a>, a MacOS enumeration capability inspired by <a href="https://github.com/GhostPack/Seatbelt">SeatBelt</a> and created by the red-teamer Cedric Owens. Unlike other enumeration methods, Swiftbelt invokes Swift code to avoid creating command line artifacts. Notably, <strong>xcc</strong> variants are also written using Swift.</p>
<p>The signature alert indicated that Swiftbelt was written to <strong>/Users/shared/sb</strong> and executed using the bash shell interpreter, <strong>sh</strong>. The full command line observed by researchers was <strong>Users/Shared/sb /bin/sh -c /users/shared/sb \&gt; /users/shared/sb.log 2\&gt;&amp;1</strong> , demonstrating that the threat actor captured results in <strong>sb.log</strong> while errors were directed to STDOUT.</p>
<h2>Diamond Model</h2>
<p>Elastic Security 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/pt/security-labs/assets/images/inital-research-of-jokerspy/image1.png" alt="REF9134 Diamond Model" /></p>
<h2>Observed tactics and techniques</h2>
<h3>MITRE ATT&amp;CK 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. These are the tactics observed by Elastic Security Labs in this campaign:</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/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/TA0007">Discovery</a></li>
</ul>
<h3>MITRE ATT&amp;CK Techniques / Sub techniques</h3>
<p>Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action. These are the techniques observed by Elastic Security Labs in this campaign:</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1059">Command and Scripting Interpreter</a></li>
<li><a href="https://attack.mitre.org/techniques/T1574/004">Dylib Hijacking</a></li>
<li><a href="https://attack.mitre.org/techniques/T1068">Potential Exploitation for Privilege Execution</a></li>
<li><a href="https://attack.mitre.org/techniques/T1548">Potential Abuse Elevation Control Mechanism</a></li>
<li><a href="https://attack.mitre.org/techniques/T1564">Hide Artifacts</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036">Masquerading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1027">Obfuscating Files or Information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1553">Subvert Trust Controls</a></li>
<li><a href="https://attack.mitre.org/techniques/T1010">Application Window Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1113">Screen Capture</a></li>
<li><a href="https://attack.mitre.org/software/S0498">Crytpoistic Software</a></li>
<li><a href="https://attack.mitre.org/techniques/T1005">Data from Local System</a></li>
</ul>
<h2>Detection logic</h2>
<h3>YARA</h3>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the JOKERSPY backdoor and SwiftBelt tool.</p>
<pre><code>rule Macos_Hacktool_JokerSpy {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-06-19&quot;
        last_modified = &quot;2023-06-19&quot;
        os = &quot;MacOS&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Hacktool&quot;
        family = &quot;JokerSpy&quot;
        threat_name = &quot;Macos.Hacktool.JokerSpy&quot;
        reference_sample = &quot;d895075057e491b34b0f8c0392b44e43ade425d19eaaacea6ef8c5c9bd3487d8&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $str1 = &quot;ScreenRecording: NO&quot; fullword
        $str2 = &quot;Accessibility: NO&quot; fullword
        $str3 = &quot;Accessibility: YES&quot; fullword
        $str4 = &quot;eck13XProtectCheck&quot;
        $str5 = &quot;Accessibility: NO&quot; fullword
        $str6 = &quot;kMDItemDisplayName = *TCC.db&quot; fullword
    condition:
        5 of them
}
</code></pre>
<pre><code>rule MacOS_Hacktool_Swiftbelt {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2021-10-12&quot;
        last_modified = &quot;2021-10-25&quot;
        threat_name = &quot;MacOS.Hacktool.Swiftbelt&quot;
        reference_sample = &quot;452c832a17436f61ad5f32ee1c97db05575160105ed1dcd0d3c6db9fb5a9aea1&quot;
        os = &quot;macos&quot;
        arch_context = &quot;x86&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $dbg1 = &quot;SwiftBelt/Sources/SwiftBelt&quot;
        $dbg2 = &quot;[-] Firefox places.sqlite database not found for user&quot;
        $dbg3 = &quot;[-] No security products found&quot;
        $dbg4 = &quot;SSH/AWS/gcloud Credentials Search:&quot;
        $dbg5 = &quot;[-] Could not open the Slack Cookies database&quot;
        $sec1 = &quot;[+] Malwarebytes A/V found on this host&quot;
        $sec2 = &quot;[+] Cisco AMP for endpoints found&quot;
        $sec3 = &quot;[+] SentinelOne agent running&quot;
        $sec4 = &quot;[+] Crowdstrike Falcon agent found&quot;
        $sec5 = &quot;[+] FireEye HX agent installed&quot;
        $sec6 = &quot;[+] Little snitch firewall found&quot;
        $sec7 = &quot;[+] ESET A/V installed&quot;
        $sec8 = &quot;[+] Carbon Black OSX Sensor installed&quot;
        $sec9 = &quot;/Library/Little Snitch&quot;
        $sec10 = &quot;/Library/FireEye/xagt&quot;
        $sec11 = &quot;/Library/CS/falcond&quot;
        $sec12 = &quot;/Library/Logs/PaloAltoNetworks/GlobalProtect&quot;
        $sec13 = &quot;/Library/Application Support/Malwarebytes&quot;
        $sec14 = &quot;/usr/local/bin/osqueryi&quot;
        $sec15 = &quot;/Library/Sophos Anti-Virus&quot;
        $sec16 = &quot;/Library/Objective-See/Lulu&quot;
        $sec17 = &quot;com.eset.remoteadministrator.agent&quot;
        $sec18 = &quot;/Applications/CarbonBlack/CbOsxSensorService&quot;
        $sec19 = &quot;/Applications/BlockBlock Helper.app&quot;
        $sec20 = &quot;/Applications/KextViewr.app&quot;
    condition:
        6 of them
}
</code></pre>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.bitdefender.com/blog/labs/fragments-of-cross-platform-backdoor-hint-at-larger-mac-os-attack/">https://www.bitdefender.com/blog/labs/fragments-of-cross-platform-backdoor-hint-at-larger-mac-os-attack</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>app.influmarket[.]org</td>
<td>Domain</td>
<td>n/a</td>
<td>sh.py domain</td>
</tr>
<tr>
<td>d895075057e491b34b0f8c0392b44e43ade425d19eaaacea6ef8c5c9bd3487d8</td>
<td>SHA-256</td>
<td>/Users/Shared/xcc</td>
<td>Macos.Hacktool.JokerSpy</td>
</tr>
<tr>
<td>8ca86f78f0c73a46f31be366538423ea0ec58089f3880e041543d08ce11fa626</td>
<td>SHA-256</td>
<td>/Users/Shared/sb</td>
<td>MacOS.Hacktool.Swiftbelt</td>
</tr>
<tr>
<td>aa951c053baf011d08f3a60a10c1d09bbac32f332413db5b38b8737558a08dc1</td>
<td>SHA-256</td>
<td>/Users/Shared/sh.py</td>
<td>sh.py script</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/inital-research-of-jokerspy/photo-edited-04@2x.jpg" length="0" type="image/jpg"/>
        </item>
    </channel>
</rss>